Skip to content

Commit c0dd9d1

Browse files
NikolayPianikovNikolayPianikov
NikolayPianikov
authored and
NikolayPianikov
committed
#29 runAs doesn't work on agent on mac os
1 parent 9e44694 commit c0dd9d1

File tree

11 files changed

+356
-78
lines changed

11 files changed

+356
-78
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
When building, testing, and deploying an application with TeamCity, you may need to run a build under a specific user account, different from the one used to run the build agent.
44

5-
The teamcity-runas plugin can be used to run TeamCity build steps under a specified user account on Windows or Linux. See [Wiki](https://github.com/JetBrains/teamcity-runas-plugin/wiki) for more information:
5+
The teamcity-runas plugin can be used to run TeamCity build steps under a specified user account on Windows, Mac or Linux. See [Wiki](https://github.com/JetBrains/teamcity-runas-plugin/wiki) for more information:
66

77
* [How to Install](https://github.com/JetBrains/teamcity-runas-plugin/wiki/How-to-install)
88

cmd/runAs_mac.sh

+171
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
#!/bin/bash
2+
3+
# runAs (settings_file_name, command, bitness, password)
4+
if [ $# -eq 4 ];
5+
then
6+
# unquote args
7+
eval "argsFile="$1""
8+
args=$(cat "$argsFile")
9+
eval "command="$2""
10+
eval "password="$4""
11+
12+
# ensure runAs user has the read/write access for temp directory
13+
chmod a+rwX "$TMPDIR"
14+
15+
# if root
16+
if [[ "$EUID" -eq 0 ]];
17+
then
18+
# auth
19+
su -c "\"${0}\" auth \"$password\"" "$args"
20+
authCode=$?
21+
22+
if [ "$authCode" = "0" ];
23+
then
24+
# su
25+
su "$args" -c "\"$command\""
26+
exit $?
27+
else
28+
echo "##teamcity[message text='Can't run under ROOT user' status='ERROR']"
29+
exit 255
30+
fi
31+
fi
32+
33+
# if not root
34+
# Check an agent will be able to remove temporary files
35+
tmpScriptFile=$(mktemp "$TMPDIR"/XXXXXXXX)
36+
tmpFile=$tmpScriptFile.tmp
37+
38+
echo "#!/bin/bash" > "$tmpScriptFile"
39+
echo "touch \"$tmpFile\"" >> "$tmpScriptFile"
40+
chmod a+rwx "$tmpScriptFile"
41+
42+
# Create temp file under the runAs user
43+
"${0}" runAs "$args" "$tmpScriptFile" "$password" arg5 &>/dev/null
44+
exitCode=$?
45+
46+
if [ "$exitCode" != "0" ];
47+
then
48+
echo "##teamcity[message text='User \"$args\" has no required permissions for target directory|n \"$TMPDIR\".|n Make sure this user has permissions to write and to execute files in the target directory (rwx)|n and to search (X) in all its parent directories' status='ERROR']"
49+
exit 255
50+
fi
51+
52+
# check that agent won't be able to remove temporary files created by the build step
53+
rm "$tmpFile" &>/dev/null
54+
55+
if [ -f "$tmpFile" ]; then
56+
rm "$tmpScriptFile" &>/dev/null
57+
echo ##teamcity[message text='Incorrect runAs configuration: agent won't be able to remove temporary files created by the build step, see teamcity-agent.log for details .' status='ERROR']
58+
exit 1
59+
else
60+
# forcible remove tmp file
61+
echo "#!/bin/bash" > "$tmpScriptFile"
62+
echo "rm \"$tmpFile\" &>/dev/null" >> "$tmpScriptFile"
63+
chmod a+rwx "$tmpScriptFile"
64+
"${0}" runAs "$args" "$tmpScriptFile" "$password" arg5 &>/dev/null
65+
rm "$tmpScriptFile" &>/dev/null
66+
fi
67+
68+
# Run as user
69+
"${0}" runAs "$args" "$command" "$password" arg5
70+
71+
exit $?
72+
fi
73+
74+
# runAs (runAs, args, command, password, arg5)
75+
if [ $# -eq 5 ];
76+
then
77+
# runAs without ROOT
78+
if [ "$1" = "runAs" ];
79+
then
80+
# check installed socat
81+
socat -h &>/dev/null
82+
socatExitCode=$?
83+
if [ "$socatExitCode" != "0" ];
84+
then
85+
echo "##teamcity[message text='socat was not installed, see https://github.com/JetBrains/teamcity-runas-plugin/wiki/How-to-install#teamcity-agent-on-linux' status='ERROR']"
86+
exit 255
87+
fi
88+
89+
args="$2"
90+
command="$3"
91+
password="$4"
92+
93+
tmpFile=$(mktemp "$TMPDIR"/XXXXXXXX)
94+
touch "$tmpFile"
95+
chmod a+rw "$tmpFile"
96+
97+
cmd="'${0}' su '$tmpFile' '$command' '$args' arg5"
98+
eval "export -- SOCAT_CMD=\"$cmd\""
99+
100+
# run command
101+
(
102+
# wait for password input
103+
attempts=50
104+
while [[ ! -s "$tmpFile" || attemps -gt 0 ]];
105+
do
106+
sleep .1
107+
attempts=$((attempts-1))
108+
done
109+
110+
if [[ $attempts -eq 0 ]];
111+
then
112+
echo "##teamcity[message text='Error during sending password' status='ERROR']"
113+
exit 255
114+
fi
115+
116+
# send password to su stdIn
117+
echo "$password"
118+
119+
# wait for process finish
120+
while ps axg | grep "$tmpFile" | grep -v "grep" > /dev/null;
121+
do
122+
sleep .1
123+
done
124+
) | (
125+
# su
126+
socat - $'EXEC:"bash -exec +x \'eval $SOCAT_CMD\'",pty,ctty,setsid'
127+
) 1> >(tee > "$tmpFile" >(grep -v "[Pp]assword:" >&1))
128+
129+
# if exit file is empty
130+
if [ ! -s "$tmpFile" ];
131+
then
132+
exit 255
133+
fi
134+
135+
# take exit code from file
136+
read -r exitCode<"$tmpFile"
137+
rm "$tmpFile" & > /dev/null
138+
139+
exit $exitCode
140+
fi
141+
142+
# change the user
143+
# su (su, tmp_file, command, args, arg5)
144+
if [ "$1" = "su" ];
145+
then
146+
tmpFile="$2"
147+
command="$3"
148+
args="$4"
149+
150+
su "$args" -c "\"$command\""
151+
exitCode=$?
152+
153+
echo -e "$exitCode\n" > "$tmpFile"
154+
exit $exitCode
155+
fi
156+
fi
157+
158+
echo Invalid arguments. >&2
159+
echo Usage: runAs.sh settings_file_name command_file_name bitness password >&2
160+
if [[ "$EUID" -eq 0 ]];
161+
then
162+
exit 0
163+
else
164+
# check installed socat
165+
socat -h &>/dev/null
166+
if [ "$?" = "0" ];
167+
then
168+
exit 0
169+
fi
170+
fi
171+
exit 255
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package jetbrains.buildServer.runAs.agent;
2+
3+
public interface Environment {
4+
OperationSystem getOperationSystem();
5+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package jetbrains.buildServer.runAs.agent;
2+
3+
import com.intellij.openapi.util.SystemInfo;
4+
5+
public class EnvironmentImpl implements Environment {
6+
@Override
7+
public OperationSystem getOperationSystem() {
8+
if(SystemInfo.isWindows) {
9+
return OperationSystem.Windows;
10+
}
11+
12+
if(SystemInfo.isMac) {
13+
return OperationSystem.Mac;
14+
}
15+
16+
return OperationSystem.Other;
17+
}
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package jetbrains.buildServer.runAs.agent;
2+
3+
public enum OperationSystem {
4+
Windows,
5+
6+
Mac,
7+
8+
Other
9+
}

0 commit comments

Comments
 (0)