-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathtinycloudinit.sh
executable file
·140 lines (126 loc) · 4.63 KB
/
tinycloudinit.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#!/bin/bash
#Tiny contextualization script, supporting a minimal set of Cloud-init syntax.
#It requires linux core utils or busybox and bash
#Retreive contextualization information
CS=/tmp/$RANDOM$RANDOM.cinit
rm -f $CS
##OpenNebula and OpenStack ConfigDrive
echo -n "Trying OpenNebula and ConfigDrive datasource..."
mkdir -p $CS.rom
blkid -t TYPE="iso9660" -o device | while read name; do
mount -o ro -t iso9660 $name $CS.rom
if [ -f $CS.rom/context.sh ]; then
sed -n "s|^ *USER_DATA *= *[\"']*\(.*\)[\"']$|\1|p" $CS.rom/context.sh > $CS
fi
if [ -f $CS.rom/ec2/latest/user-data ]; then
cp $CS.rom/ec2/latest/user-data $CS
elif [ -f $CS.rom/openstack/latest/user-data ]; then
cp $CS.rom/openstack/latest/user-data $CS
fi
umount $CS.rom
done
rmdir $CS.rom
[ -f $CS ] && echo "got it!" || echo "failed!"
##Amazon EC2
if [ ! -f $CS ]; then
echo -n "Trying Amazon EC2 datasource..."
wget -T 5 http://169.254.169.254/latest/user-data -q -O $CS &>/dev/null
[ -f $CS ] && echo "got it!" || echo "failed!"
fi
#If user data is not provided, nothing to be done
if [[ ! -s $CS ]]; then
echo "Cannot find any userdata or userdata is empty. Nothing to do..."
exit 0
fi
#Decode user data (if not already decoded)
if ! [[ "`head -c 12 $CS`" == "Content-Type" || "`head -c 1 $CS`" == "#" ]]; then
echo "Data source seems to be encoded in base64. I will decode it."
base64 -d $CS > $CS.new
mv $CS.new $CS
fi
#Parse MIME encoding if present
BOUNDARY=`head -1 $CS | sed -n "s|^Content-Type: *multipart/mixed; *boundary *= *[\"']*\([^\"']*\)[\"']*$|\1|p"`
if [ -n "$BOUNDARY" ]; then
echo "Data source seems to be encoded in MIME format. I will decode it."
awk -v B="$BOUNDARY" -v F="$CS." '{if($0=="--"B"--"){exit}if($0=="--"B){k=k+1;f=F k;getline;s=1;printf "" > f};if(s==1)print $0 >> f}' $CS
rm -f $CS
fi
#Execute contextualization commands
for f in $CS*; do
#Skip content-type (if present)
if [ "`head -c 13 $f`" == "Content-Type:" ]; then
awk '{if($0==""){s=1;getline;}if(s==1)print $0}' $f > $f.new
mv $f.new $f
fi
#Skip files not containing #
[ "`head -c 1 $f`" == "#" ] || continue
#Execute contextualization command
FIRST_LINE="`head -1 $f`"
if [ "$FIRST_LINE" == "#!/bin/bash" ]; then
#This is a bash script, let's just execute it
echo "Executing Bash contextualization script..."
which bash &>/dev/null
if [ $? -ne 0 ]; then
which ash &>/dev/null
if [ $? -eq 0 ]; then
ash $f
else
echo "error. No bash or ash present"
fi
else
bash $f
fi
elif [ "$FIRST_LINE" == "#!/bin/sh" ]; then
#This is a shell script, let's just execute it
echo "Executing Shell contextualization script..."
sh $f
elif [ "$FIRST_LINE" == "#cloud-config" ]; then
#This is a YAML Cloud config script, we need to parse it. This is only partially implemented here
newuser(){
echo -n "Creating user $1..."
un="$1"
ud=
i=0
while [ $# -gt 0 ]; do
case $1 in
-k) uk="$uk$2\n"; shift 2;;
-S) uS="$2"; shift 2;;
-g) ud="$ud $1 $2"; addgroup $2 &>/dev/null; shift 2;;
-G) ud="$ud $1 $2"; for g in ${2//,/ }; do groupadd -f $g; done; shift 2;;
*) ud="$ud $1"; shift 1;;
esac
done
id $un &>/dev/null
if [ $? -eq 0 ]; then
echo -n "already exists..."
else
adduser $ud &>/dev/null
fi
ung="`id -g $un &>/dev/null`"
if [ $? -ne 0 ]; then
echo "error!"
return
fi
unh=`eval echo ~${un}`
if [[ -n "$uk" ]]; then
mkdir -p $unh/.ssh/
echo -e "$uk" >> $unh/.ssh/authorized_keys
chown $un:$ung -R $unh/.ssh
chmod og-rwx $unh/.ssh
fi
if [[ -n "$uS" ]]; then
[ "$uS" == "ALL=(ALL)NOPASSWD" ] && uS="ALL=(ALL) NOPASSWD:ALL"
[ "$uS" == "ALL=(ALL)ALL" ] && uS="ALL=(ALL) ALL"
grep -q -F "$un $uS" /etc/sudoers || echo "$un $uS" >> /etc/sudoers
fi
echo "ok!"
}
awk 'BEGIN{FS=":|-"}{gsub(/^[ \t]+/,"",$1);gsub(/^[ \t]+/,"",$2);gsub(/^[ \t]+/,"",$3);if($1=="users"){u=1}if(u==1){if(ua!=""){if($1=="primary-group")ua=ua" -g \""$2"\"";if($1=="groups")ua=ua" -G \""$2"\"";if($1=="sudo")ua=ua" -S \""$2"\"";if($1=="passwd")ua=ua" -p \""$2"\"";if($1=="ssh"&&$2=="authorized"){while(1){getline;k=$0;gsub(/^[ \t]+-[ ]+/,"",k);if(k!~/^ssh-rsa/)break;ua=ua" -k \""k"\""}}}if($1==""&&$2=="name"){if(ua!=""){print "newuser "ua;}ua=$3;}}}END{if(ua!=""){print "newuser "ua;}}' $f | while read line; do
eval $line
done
else
#Other formats are unsupported
echo "Ignoring script starting with `head -1 $f | head -c 100`. Not supported."
fi
done
exit 0