Skip to content

Instantly share code, notes, and snippets.

@kgilpin
Last active February 11, 2016 22:23
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kgilpin/7f6bd5e3ca1d84856879 to your computer and use it in GitHub Desktop.
Save kgilpin/7f6bd5e3ca1d84856879 to your computer and use it in GitHub Desktop.
Conjur Traffic Auth for the Truly Paranoid

Approach

Create distinct roles with specific permissions to call untrusted web services.

Client services authenticate as one of these roles when calling an untrusted web service.

Discussion

When using an externalized (Nginx) forwarder and gatekeeper, a webservice client can send a Conjur access token for its own identity. The client doesn't have to worry about the gatekeeper misusing the access token, because the gatekeeper is trusted code.

When calling an untrusted webservice (e.g. a custom webservice which is doing custom auth in code using Conjurauth), the service client should use a weaker token for authorization. This token should have the minimum necessary privileges; essentially, no privileges beyond the right to call the untrusted service.

Conjur's authn-tv service provides a way to obtain "scoped" (to use the OAuth terminology) API keys. A scoped API key (aka refresh token) allows an authn-tv client role to authenticate as another role. This process is subject to a few simple rules:

  • authn-tv requires that clients have execute privilege on the authn-tv webservice resource.
  • An authn-tv client can only obtain an API key for a role which the client actually has. In other words, authn-tv can only be used to narrow privileges, not to widen them.
  • API keys which are issued by authn-tv must be submitted back to the authn-tv service to obtain an access token. The standard Conjur authn service will not recognize API keys which are issued by authn-tv.
  • authn-tv clients can, and should, revoke the API keys which were issued by authn-tv once they are no longer needed.

The procedure for calling an untrusted web service looks like this:

  • At startup time, the client uses authn-tv to obtain API keys for a scoped set of roles. Each "scoped" role is a role which has the privileges necessary to call a specific untrusted webservice.
  • When the client wants to call an untrusted webservice, it submits the scoped API key to authn-tv to obtain an access token.
  • This access token is sent to the untrusted webservice as proof of authentication and authorization.
  • When the client program shuts down, it instructs authn-tv to revoke the scoped API keys.
#!/bin/bash -e
echo Loading policy
conjur policy2 load --namespace untrusted-service-demo https://gist.githubusercontent.com/kgilpin/7f6bd5e3ca1d84856879/raw/policy.yml
conjur policy2 load https://gist.githubusercontent.com/kgilpin/7f6bd5e3ca1d84856879/raw/entitlements.yml
echo Policy loaded
host=client-a/host-001
echo Creating host $host
conjur host create $host | tee host-001.json
conjur layer hosts add untrusted-service-demo/client-a $host
echo Host created and added to layer untrusted-service-demo/client-a
export CONJUR_AUTHN_LOGIN=host/$host
export CONJUR_AUTHN_API_KEY=$(cat host-001.json | jq -r .api_key)
host_token=$(conjur authn authenticate -H)
echo Obtaining scoped API key
scoped_api_key=$(curl -s -k -H "$host_token" -X POST https://conjur/api/authn-tv/tokens --data "group/untrusted-service-demo/client-a/service-a-client")
echo $scoped_api_key
echo Obtaining scoped access token
scoped_token="Authorization: Token token=\"$(curl -s -k -X POST https://conjur/api/authn-tv/users/group/untrusted-service-demo/client-a/service-a-client/authenticate --data $scoped_api_key | base64 -w0)\""
echo OK
echo What are all resources that the scoped identity can see?
curl -s -k -H "$scoped_token" https://conjur/api/authz/cucumber/resources | jq "map(.id)"
echo Just the webservice
for privilege in read execute update; do
echo Can the scoped identity $privilege the web service? \(204 means yes\)
curl -s -o /dev/null -w "%{http_code}" -k -H "$scoped_token" "https://conjur/api/authz/cucumber/resources/webservice/untrusted-service-demo/service-a?check&privilege=$privilege"
echo
done
echo Revoking the scoped API key
curl -s -o /dev/null -w "%{http_code}" -k -H "$host_token" -X DELETE https://conjur/api/authn-tv/tokens/$scoped_api_key
echo Attempting to use the API key after it\'s been revoked
curl -s -o /dev/null -w "%{http_code}" -k -X POST https://conjur/api/authn-tv/users/group/untrusted-service-demo/client-a/service-a-client/authenticate --data $scoped_api_key
# This is an entitlement to hook up client-a/service-a-client to Webservice service-a
- !grant
role: !group untrusted-service-demo/service-a/client
member: !group untrusted-service-demo/client-a/service-a-client
# Allow Layer client-a to use authn-tv
- !permit
role: !layer untrusted-service-demo/client-a
privilege: execute
resource: !webservice authn-tv
# A policy for an untrusted web service. The group 'client' has
# read and execute privilege on the web service.
- !policy
id: service-a
body:
# The service code will verify that inbound requests have "execute" privilege on this webservice.
- !webservice
# Members of this group will be permitted to call the webservice.
- !group client
# Here's where the permission between the group and the webservice is defined.
- !permit
role: !group client
privilege: execute
resource: !webservice
replace: true
# A policy for a web service client.
- !policy
id: client-a
body:
# This is the "scoped" role that will be used to call the untrusted service-a.
- !group service-a-client
# Machines in client-a belong to this layer and inherit its privileges.
- !layer
# Grant the service-a-client role to the layer, so that members of the layer
# can use authn-tv to authenticate as the service-a-client role.
- !grant
role: !group service-a-client
member: !layer
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment