Skip to content

Commit

Permalink
Upload pubkey through Google Cloud SDK
Browse files Browse the repository at this point in the history
  • Loading branch information
dinvlad committed Aug 15, 2020
1 parent ddec96c commit 4e236a2
Show file tree
Hide file tree
Showing 4 changed files with 18 additions and 53 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@
*_cache*
*cache_*
.vscode/*

**.pem
31 changes: 13 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,42 +39,37 @@ pip3 install google-yubikey
or to renew it after expiration:

```
google-yubikey generate-key
google-yubikey generate-key > yubikey.pem
```

3. Install and authenticate with
[Google Cloud SDK](https://cloud.google.com/sdk/install):
3. Install [Google Cloud SDK](https://cloud.google.com/sdk/install) and run:

```
gcloud auth application-default login
gcloud auth login
gcloud beta iam service-accounts keys upload yubikey.pem \
--iam-account <service_account_email>
gcloud auth revoke # optional, but recommended
```

This is needed only for initially setting up YubiKey with a Service Account.
This is needed only for setting up YubiKey with a Service Account.
Your user account must have at least `Service Account Key Admin` role
or `iam.serviceAccountKeys.create` permission
on the target Service Account(s).

4. Run this once to associate your YubiKey with each Service Account:

```
google-yubikey upload-key -a <service_account_email>
```

5. As a good practice, revoke your Google Cloud SDK credentials,
As a good practice, the last command revokes your Google Cloud SDK credentials,
which limits the potential for their exposure
only to the time of the public key upload:
only to the time of the public key upload.

```
gcloud auth application-default revoke
```
Alernatively to step 3, you can upload `yubikey.pem` from step 2 via
Google Cloud Console for the target Service Account(s).

6. Run this every time you'd like to generate a Service Account token:
4. Run this every time you'd like to generate a Service Account token:

```
google-yubikey token -a <service_account_email>
```

7. Further customization options are available through:
5. Further customization options are available through:

```
google-yubikey [<command>] -h
Expand Down
37 changes: 3 additions & 34 deletions google_yubikey/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,7 @@
import warnings

import requests
from click import Context, Command
from cryptography.hazmat.primitives import serialization
from googleapiclient.discovery import build as google_api
from ykman.descriptor import open_device
from ykman.cli.util import prompt_for_touch
from ykman.piv import \
Expand Down Expand Up @@ -51,7 +49,6 @@ def convert(str_value: str):
class Action(ArgEnum):
""" Action type """
GENERATE_KEY = 1
UPLOAD_KEY = 2
TOKEN = 3


Expand Down Expand Up @@ -131,16 +128,6 @@ def parse_args():
help='Prompt for management key',
)

# "upload-key" action
parser_upload_key = subparsers.add_parser(
str(Action.UPLOAD_KEY),
help='Associate public key of the YubiKey with a Service Account',
)
parser_upload_key.add_argument(
'-a', '--service-account-email', required=True,
help='Service Account email',
)

# "token" action
parser_token = subparsers.add_parser(
str(Action.TOKEN),
Expand Down Expand Up @@ -210,6 +197,7 @@ def gen_private_key(yubikey: YubiKey, slot: SLOT, prompt_management_key: bool,
slot.value, public_key, subject, start, end,
touch_callback=prompt_for_touch,
)
return get_public_key(yubikey, slot)


def get_public_key(yubikey: YubiKey, slot: SLOT):
Expand All @@ -218,22 +206,6 @@ def get_public_key(yubikey: YubiKey, slot: SLOT):
return cert.public_bytes(serialization.Encoding.PEM)


def upload_pubkey(service_account_email: str, public_key: bytes):
""" Registers Google Service Account public key """
info('Uploading public key...')
warnings.filterwarnings(
"ignore", "Your application has authenticated using end user credentials"
)
# pylint: disable=maybe-no-member
response = google_api('iam', 'v1').projects().serviceAccounts().keys().upload(
name=f'projects/-/serviceAccounts/{service_account_email}',
body={
'publicKeyData': b64encode_str(public_key),
},
).execute()
return response['name'].split('/')[-1]


def b64encode_str(bbytes: bytes):
""" Encodes bytes as base64 string """
return b64encode(bbytes).decode('utf-8')
Expand Down Expand Up @@ -293,15 +265,12 @@ def main():
yubikey = get_yubikey()

if args.action == str(Action.GENERATE_KEY):
gen_private_key(
public_key = gen_private_key(
yubikey, args.slot, args.prompt_management_key,
args.pin_policy, args.touch_policy,
args.subject, args.valid_days,
)
elif args.action == str(Action.UPLOAD_KEY):
public_key = get_public_key(yubikey, args.slot)
key_id = upload_pubkey(args.service_account_email, public_key)
info(f'Key id: {key_id}')
print(public_key.decode('utf-8'))
else:
id_token = get_id_token(
yubikey, args.slot, args.prompt_management_key,
Expand Down
1 change: 0 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
'relative_to': __file__,
},
install_requires=[
'google-api-python-client >= 1.10.0',
'requests >= 2.24.0',
'yubikey-manager >= 3.1.1',
],
Expand Down

0 comments on commit 4e236a2

Please sign in to comment.