~devstack-core/devstack/github

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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
#!/usr/bin/env bash

# **create_userrc.sh**

# Pre-create rc files and credentials for the default users.

# Warning: This script just for development purposes

set -o errexit
set -o xtrace

ACCOUNT_DIR=./accrc

function display_help {
cat <<EOF

usage: $0 <options..>

This script creates certificates and sourcable rc files per tenant/user.

Target account directory hierarchy:
target_dir-|
           |-cacert.pem
           |-tenant1-name|
           |             |- user1
           |             |- user1-cert.pem
           |             |- user1-pk.pem
           |             |- user2
           |             ..
           |-tenant2-name..
           ..

Optional Arguments
-P include password to the rc files; with -A it assume all users password is the same
-A try with all user
-u <username> create files just for the specified user
-C <tenant_name> create user and tenant, the specifid tenant will be the user's tenant
-r <name> when combined with -C and the (-u) user exists it will be the user's tenant role in the (-C)tenant (default: Member)
-p <userpass> password for the user
--heat-url <heat_url>
--os-username <username>
--os-password <admin password>
--os-tenant-name <tenant_name>
--os-tenant-id <tenant_id>
--os-auth-url <auth_url>
--os-cacert <cert file>
--target-dir <target_directory>
--skip-tenant <tenant-name>
--debug

Example:
$0 -AP
$0 -P -C mytenant -u myuser -p mypass
EOF
}

if ! options=$(getopt -o hPAp:u:r:C: -l os-username:,os-password:,os-tenant-name:,os-tenant-id:,os-auth-url:,target-dir:,heat-url:,skip-tenant:,os-cacert:,help,debug -- "$@"); then
    display_help
    exit 1
fi
eval set -- $options
ADDPASS=""
HEAT_URL=""

# The services users usually in the service tenant.
# rc files for service users, is out of scope.
# Supporting different tenant for services is out of scope.
SKIP_TENANT="service"
MODE=""
ROLE=Member
USER_NAME=""
USER_PASS=""
while [ $# -gt 0 ]; do
    case "$1" in
    -h|--help) display_help; exit 0 ;;
    --os-username) export OS_USERNAME=$2; shift ;;
    --os-password) export OS_PASSWORD=$2; shift ;;
    --os-tenant-name) export OS_TENANT_NAME=$2; shift ;;
    --os-tenant-id) export OS_TENANT_ID=$2; shift ;;
    --skip-tenant) SKIP_TENANT="$SKIP_TENANT$2,"; shift ;;
    --os-auth-url) export OS_AUTH_URL=$2; shift ;;
    --os-cacert) export OS_CACERT=$2; shift ;;
    --target-dir) ACCOUNT_DIR=$2; shift ;;
    --heat-url) HEAT_URL=$2; shift ;;
    --debug) set -o xtrace ;;
    -u) MODE=${MODE:-one};  USER_NAME=$2; shift ;;
    -p) USER_PASS=$2; shift ;;
    -A) MODE=all; ;;
    -P) ADDPASS="yes" ;;
    -C) MODE=create; TENANT=$2; shift ;;
    -r) ROLE=$2; shift ;;
    (--) shift; break ;;
    (-*) echo "$0: error - unrecognized option $1" >&2; display_help; exit 1 ;;
    (*)  echo "$0: error - unexpected argument $1" >&2; display_help; exit 1 ;;
    esac
    shift
done

if [ -z "$OS_PASSWORD" ]; then
    if [ -z "$ADMIN_PASSWORD" ];then
        echo "The admin password is required option!"  >&2
        exit 2
    else
        OS_PASSWORD=$ADMIN_PASSWORD
    fi
fi

if [ -z "$OS_TENANT_NAME" -a -z "$OS_TENANT_ID" ]; then
    export OS_TENANT_NAME=admin
fi

if [ -z "$OS_USERNAME" ]; then
    export OS_USERNAME=admin
fi

if [ -z "$OS_AUTH_URL" ]; then
    export OS_AUTH_URL=http://localhost:5000/v2.0/
fi

USER_PASS=${USER_PASS:-$OS_PASSWORD}
USER_NAME=${USER_NAME:-$OS_USERNAME}

if [ -z "$MODE" ]; then
    echo "You must specify at least -A or -u parameter!"  >&2
    echo
    display_help
    exit 3
fi

export -n SERVICE_TOKEN SERVICE_ENDPOINT OS_SERVICE_TOKEN OS_SERVICE_ENDPOINT

EC2_URL=$(openstack endpoint show -f value -c publicurl ec2 || true)
if [[ -z $EC2_URL ]]; then
    EC2_URL=http://localhost:8773/
fi

S3_URL=$(openstack endpoint show -f value -c publicurl s3 || true)
if [[ -z $S3_URL ]]; then
    S3_URL=http://localhost:3333
fi

mkdir -p "$ACCOUNT_DIR"
ACCOUNT_DIR=`readlink -f "$ACCOUNT_DIR"`
EUCALYPTUS_CERT=$ACCOUNT_DIR/cacert.pem
if [ -e "$EUCALYPTUS_CERT" ]; then
    mv "$EUCALYPTUS_CERT" "$EUCALYPTUS_CERT.old"
fi
if ! nova x509-get-root-cert "$EUCALYPTUS_CERT"; then
    echo "Failed to update the root certificate: $EUCALYPTUS_CERT" >&2
    if [ -e "$EUCALYPTUS_CERT.old" ]; then
        mv "$EUCALYPTUS_CERT.old" "$EUCALYPTUS_CERT"
    fi
fi


function add_entry {
    local user_id=$1
    local user_name=$2
    local tenant_id=$3
    local tenant_name=$4
    local user_passwd=$5

    # The admin user can see all user's secret AWS keys, it does not looks good
    local line=`openstack ec2 credentials list --user $user_id | grep " $tenant_id "`
    if [ -z "$line" ]; then
        openstack ec2 credentials create --user $user_id --project $tenant_id 1>&2
        line=`openstack ec2 credentials list --user $user_id | grep " $tenant_id "`
    fi
    local ec2_access_key ec2_secret_key
    read ec2_access_key ec2_secret_key <<<  `echo $line | awk '{print $2 " " $4 }'`
    mkdir -p "$ACCOUNT_DIR/$tenant_name"
    local rcfile="$ACCOUNT_DIR/$tenant_name/$user_name"
    # The certs subject part are the tenant ID "dash" user ID, but the CN should be the first part of the DN
    # Generally the subject DN parts should be in reverse order like the Issuer
    # The Serial does not seams correctly marked either
    local ec2_cert="$rcfile-cert.pem"
    local ec2_private_key="$rcfile-pk.pem"
    # Try to preserve the original file on fail (best effort)
    if [ -e "$ec2_private_key" ]; then
        mv -f "$ec2_private_key" "$ec2_private_key.old"
    fi
    if [ -e "$ec2_cert" ]; then
        mv -f "$ec2_cert" "$ec2_cert.old"
    fi
    # It will not create certs when the password is incorrect
    if ! nova --os-password "$user_passwd" --os-username "$user_name" --os-tenant-name "$tenant_name" x509-create-cert "$ec2_private_key" "$ec2_cert"; then
        if [ -e "$ec2_private_key.old" ]; then
            mv -f "$ec2_private_key.old" "$ec2_private_key"
        fi
        if [ -e "$ec2_cert.old" ]; then
            mv -f "$ec2_cert.old" "$ec2_cert"
        fi
    fi
    cat >"$rcfile" <<EOF
# you can source this file
export EC2_ACCESS_KEY="$ec2_access_key"
export EC2_SECRET_KEY="$ec2_secret_key"
export EC2_URL="$EC2_URL"
export S3_URL="$S3_URL"
# OpenStack USER ID = $user_id
export OS_USERNAME="$user_name"
# OpenStack Tenant ID = $tenant_id
export OS_TENANT_NAME="$tenant_name"
export OS_AUTH_URL="$OS_AUTH_URL"
export OS_CACERT="$OS_CACERT"
export EC2_CERT="$ec2_cert"
export EC2_PRIVATE_KEY="$ec2_private_key"
export EC2_USER_ID=42 #not checked by nova (can be a 12-digit id)
export EUCALYPTUS_CERT="$ACCOUNT_DIR/cacert.pem"
export NOVA_CERT="$ACCOUNT_DIR/cacert.pem"
EOF
    if [ -n "$ADDPASS" ]; then
        echo "export OS_PASSWORD=\"$user_passwd\"" >>"$rcfile"
    fi
    if [ -n "$HEAT_URL" ]; then
        echo "export HEAT_URL=\"$HEAT_URL/$tenant_id\"" >>"$rcfile"
        echo "export OS_NO_CLIENT_AUTH=True" >>"$rcfile"
    fi
}

#admin users expected
function create_or_get_project {
    local name=$1
    local id
    eval $(openstack project show -f shell -c id $name)
    if [[ -z $id ]]; then
        eval $(openstack project create -f shell -c id $name)
    fi
    echo $id
}

function create_or_get_role {
    local name=$1
    local id
    eval $(openstack role show -f shell -c id $name)
    if [[ -z $id ]]; then
        eval $(openstack role create -f shell -c id $name)
    fi
    echo $id
}

# Provides empty string when the user does not exists
function get_user_id {
    openstack user list | grep " $1 " | cut -d " " -f2
}

if [ $MODE != "create" ]; then
    # looks like I can't ask for all tenant related to a specified user
    openstack project list --long --quote none -f csv | grep ',True' | grep -v "${SKIP_TENANT}" | while IFS=, read tenant_id tenant_name desc enabled; do
        openstack user list --project $tenant_id --long --quote none -f csv | grep ',True' | while IFS=, read user_id user_name project email enabled; do
            if [ $MODE = one -a "$user_name" != "$USER_NAME" ]; then
                continue;
            fi

            # Checks for a specific password defined for an user.
            # Example for an username johndoe: JOHNDOE_PASSWORD=1234
            # This mechanism is used by lib/swift
            eval SPECIFIC_UPASSWORD="\$${user_name}_password"
            if [ -n "$SPECIFIC_UPASSWORD" ]; then
                USER_PASS=$SPECIFIC_UPASSWORD
            fi
            add_entry "$user_id" "$user_name" "$tenant_id" "$tenant_name" "$USER_PASS"
        done
    done
else
    tenant_name=$TENANT
    tenant_id=$(create_or_get_project "$TENANT")
    user_name=$USER_NAME
    user_id=`get_user_id $user_name`
    if [ -z "$user_id" ]; then
        eval $(openstack user create "$user_name" --project "$tenant_id" --password "$USER_PASS" --email "$user_name@example.com" -f shell -c id)
        user_id=$id
        add_entry "$user_id" "$user_name" "$tenant_id" "$tenant_name" "$USER_PASS"
    else
        role_id=$(create_or_get_role "$ROLE")
        openstack role add "$role_id" --user "$user_id" --project "$tenant_id"
        add_entry "$user_id" "$user_name" "$tenant_id" "$tenant_name" "$USER_PASS"
    fi
fi