Implement ServiceAccount.get_email() in service_account recipe module |
||
Issue descriptionThis one: https://chromium.googlesource.com/infra/luci/recipes-py/+/0584da0c3d052d75bba9cd4108b307f43852024a/recipe_modules/service_account/api.py#42 Fuchsia recipes want to use it. Will likely require modifying luci-auth binary to output the email in a structured form (as part of JSON struct), so it can be picked up from recipes without string parsing.
,
Mar 7 2018
Why the email is needed exactly? Do you want to skip uploading if the email is not whitelisted in the recipe? Also, how does the dashboard authenticates calls? OAuth?
,
Mar 7 2018
Maybe I'm misunderstanding, but can't you just have each builder decide which service account to use, within the same recipe? Something like..
SERVICE_ACCOUNT_DICT = {
'Windows': '/creds/service_accounts/windows-builder.json',
'Linux': '/creds/service_accounts/linux-builder.json',
}
def RunSteps(api):
...
service_account = (
api.service_account.from_credentials_json(SERVICE_ACCOUNT_JSON[api.properties['buildername']]))
except don't use api.properties['buildername'], there's a better way I think but I forget it.
,
Mar 7 2018
I'm whitelisting all of the service accounts with the dashboard, before running the builders, so it should never be the case that an account is not whitelisted. Yes, the dashboard autheticates using OAuth tokens. I'm using the email in the following way: Fuchsia has a ServiceAccountApi recipe module at: https://fuchsia.googlesource.com/infra/recipes/+/master/recipe_modules/service_account/api.py The method `get_json_path` requires the service account name and returns a path to a JSON credentials file for the service account. I'm hoping to derive the name of the service account from `get_email()` and pass it to `get_json_path()`. I'm going to pass the path to the credentials filepath returned by `get_json_path()` to a Go binary that will generate an OAuth token from the credentials file using a LUCI authenticator, attach it to a request header, and then execute the request. That go binary's source is here: https://fuchsia.googlesource.com/infra/infra/+/master/cmd/catapult/upload.go The OAuth token is generated here: https://fuchsia.googlesource.com/infra/infra/+/master/cmd/catapult/upload.go#130
,
Mar 7 2018
martiniss@ yes that's an option I considered. It seemed better to use get_email since that would allow me to avoid having to hard-code the service account names and add new ones as I whitelist new accounts, but TBH that's a fine short term solution.
,
Mar 7 2018
I'm fine with get_email being implemented, just wanted to understand what you're doing. Up to you and vadim.
,
Mar 7 2018
Oh... I sense a confusion here. There are two flavors of service accounts used on LUCI builds: 1. Service accounts identified by JSON files with private keys. get_json_path() is about them. They are generally DEPRECATED and should eventually be removed completely. They depend on some external mechanism (Salt in Fuchsia case, Puppet in Chrome Infra case) to deploy the private key on the bot. This reduces agility of bots and not terribly secure (long lived private keys exposed to tasks). 2. Task-associated service accounts exposed through Swarming APIs. It is the one you configure in cr-buildbucket.cfg with 'service_account' field. Their private keys are not directly accessible, the task sees only short lived OAuth tokens. All LUCI libraries, and most recipes know how to grab such tokens. In your specific case I see upload.go is already using go.chromium.org/luci/auth, it means it understands how to use tokens from task-associated accounts right out of the box (this is documented in https://godoc.org/go.chromium.org/luci/auth#Method for default AutoSelectMethod, though it is probably not terribly clear...). All you need to do is just NOT pass -service-account-json to the upload binary, and it will automatically pick up the service account associated with the task if it finds itself running inside the task. (Also, upload.go does redundant work when generating OAuth tokens. Using authenticator.Client() is sufficient to authenticate calls, the http.Client there injects OAuth tokens in all requests, no need to do it explicitly with SetAuthHeader).
,
Mar 7 2018
Ah! Thanks so much for the detailed explanation. I'll fix this on our end, so no need to implement get_email and this can be closed. I'll re-open if I have more questions.
,
Mar 9 2018
|
||
►
Sign in to add a comment |
||
Comment 1 by kjharland@google.com
, Mar 7 2018