Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
toshke committed Sep 20, 2018
1 parent f3cee29 commit 98aa83d
Show file tree
Hide file tree
Showing 4 changed files with 315 additions and 0 deletions.
56 changes: 56 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
![build-status](https://travis-ci.com/theonestack/hl-component-cognito.svg?branch=master)

### Cfhighlander cognito component

Uses [cloudformation-custom-resources-js](https://github.com/base2Services/cloudformation-custom-resources-nodejs)
as a custom resource code for creating cognito clients and custom domain names.

```bash

# install highlander gem
$ gem install cfhighlander

# build and validate standalone component
$ cfcompile --validate cognito

```
### Usage

Creates Cognito UserPools. Allows adding User pool clients and custom domain name. Note that
this functionality is not supported natively via CloudFormation, and is implemented through
custom resources. Consume component with `Component 'cognito'` in your cfhiglhander template for default behaviour.
Read more on [cfhighlander page](https://github.com/theonestack/cfhighlander) on consuming, extending and inlining components.

### Configuration options

Look at `cognito.config.yaml` for format of configuration file

- `pool_name` - Explicit Cognito UserPool name
- `user_schema` - Defines user attributes.
- `groups` - Create UserGroups alongside with the pool. Allows defining name and description
- `clients` - Cognito OAuth clients to authorize against the pool. Look at `default_client` section
of the config file for required structure
- `domain_name` - Custom domain name for authentication over the web on `https://${domain_name}.auth.${aws_region}.amazoncognito.com` url
- `ccr` - Required for custom resources to be rendered. Do **NOT** alter this configuration value

### Parameters

NONE

### Outputs

`UserPoolId` - PoolId

`UserPoolArn` - Pool Amazon Resource Name (ARN)

`UserPoolProviderURL` - Provider URL

`UserPoolProviderName` - Provider Name

`PoolDomainUrl` - *(Optional)* if custom domain name is set, this will render the full url

`PoolDomainName`- *(Optional)* if custom domain name is set, this will render the domain name

`PoolClient${clietNname}Id` - *(Optional)* client id for every defined client

`PoolClient${clietNname}Secret` - *(Optional)* if client secret is configured on defined client
7 changes: 7 additions & 0 deletions cognito.cfhighlander.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
CfhighlanderTemplate do

Name 'cognito'

LambdaFunctions 'ccr'

end
159 changes: 159 additions & 0 deletions cognito.cfndsl.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
CloudFormation do


Cognito_UserPool :UserPool do
UserPoolName pool_name
AliasAttributes alias_attributes
schema = user_schema.collect do |key, val|
{ Name: key,
AttributeDataType: val['type'],
Mutable: val['mutable'],
Required: val['required'] }
end

Schema schema

end

if defined? domain_name and (not domain_name.nil?)
CloudFormation_CustomResource('PoolDomainName') do
ServiceToken FnGetAtt('ccrCognitoDN', 'Arn')
Property 'UserPoolId', Ref(:UserPool)
Property 'Domain', domain_name
Property 'GenerateRandomIfNotAvailable', 'true'
end

Output('PoolDomainUrl') do
Value(FnGetAtt('PoolDomainName', 'DomainFull'))
end
Output('PoolDomainName') do
Value(FnGetAtt('PoolDomainName', 'Domain'))
end
end


def user_pool_client(name, config)

CloudFormation_CustomResource("PoolClient#{name}") do

ServiceToken FnGetAtt('ccrCognitoUPC', 'Arn')

Property 'UserPoolId', Ref(:UserPool)
Property 'ClientName', config['name']

if config.key? 'generate_secret'
Property 'GenerateSecret', config['generate_secret']
end

if config.key? 'explicit_auth_flows'
Property 'ExplicitAuthFlows', config['explicit_auth_flows']
end

if config.key? 'callback_urls'
Property 'CallbackURLs', config['callback_urls']
end

if config.key? 'logout_urls'
Property 'LogoutURLs', config['logout_urls']
end

if config.key? 'default_redirect_uri'
Property 'DefaultRedirectURI', config['default_redirect_uri']
end

if config.key? 'read_attributes'
Property 'ReadAttributes', config['read_attributes']
end

if config.key? 'write_attributes'
Property 'WriteAttributes', config['write_attributes']
end

if config.key? 'refresh_token_validity'
Property 'RefreshTokenValidity', config['refresh_token_validity']
end

if config.key? 'allowed_oauth_flows_userpool_client'
Property 'AllowedOAuthFlowsUserPoolClient', config['allowed_oauth_flows_userpool_client']
end

if config.key? 'allowed_oauth_flows'
Property 'AllowedOAuthFlows', config['allowed_oauth_flows']
end

if config.key? 'allowed_oauth_scopes'
Property 'AllowedOAuthScopes', config['allowed_oauth_scopes']
end

if config.key? 'supported_identity_providers'
Property 'SupportedIdentityProviders', config['supported_identity_providers']
elsif config.key? 'allow_cognito_idp' and config['allow_cognito_idp']
Property 'SupportedIdentityProviders', ['COGNITO']
end

if config.key? 'skip_update'
Property 'SkipUpdate', config['skip_update']
end

end

Output("PoolClient#{name}Id") do
Value(FnGetAtt("PoolClient#{name}", 'UserPoolClient.ClientId'))
end

if (config.key? 'generate_secret') and (config['generate_secret'])
if config.key? 'output_secret' and config['output_secret']
Output("PoolClient#{name}Secret") do
Value(FnGetAtt("PoolClient#{name}", 'UserPoolClient.ClientSecret'))
end
end
end

end

def user_pool_group(name, config)
Cognito_UserPoolGroup("UserGroup#{name}") do

GroupName config['name']
Description config['description']
Precedence config['precedence'] if config.key? 'precedence'
UserPoolId Ref(:UserPool)
end
end


if defined? clients and (not clients.nil?)
clients.each do |key, config|
user_pool_client(key, config)
end
else
user_pool_client(:defaultPoolClient, default_client)
end


if defined? groups and (not groups.nil?)
groups.each do |key, config|
user_pool_group(key, config)
end
else
user_pool_group(:defaultUserGroup, default_user_group)
end


Output(:UserPoolId) do
Value(Ref(:UserPool))
end

Output(:UserPoolArn) do
Value(FnGetAtt(:UserPool, 'Arn'))
end

Output(:UserPoolProviderURL) do
Value(FnGetAtt(:UserPool, 'ProviderURL'))
end

Output(:UserPoolProviderName) do
Value(FnGetAtt(:UserPool, 'ProviderName'))
end

end
93 changes: 93 additions & 0 deletions cognito.config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
###
### For more information
### https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cognito-userpool.html
### https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cognito-userpoolgroup.html
### https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cognito-userpoolclient.html
###

pool_name: cfhighlander_user_pool
alias_attributes:
- email

# Uncomment following line, if you want user pool
# domain enabled for your cognito pool
# resulting in domain https://${domain_name}.auth.${aws_region}.amazoncognito.com
# domain_name: myscustomdomain

default_client:
name: cfhighlander_user_pool_client
generate_secret: true
output_secret: true
callback_urls:
- http://localhost:3000
logout_urls:
- http://localhost:3000/log_out
default_redirect_uri: http://localhost:3000/
allowed_oauth_scopes:
- openid
- profile
refresh_token_validity: 30
allowed_oauth_flows_userpool_client: true
allowed_oauth_flows:
- client_credentials
explicit_auth_flows: []
skip_update: false
allow_cognito_idp: true

default_user_group:
name: default_user_group
description: Update cfhighlander cognito component configuration to define user groups
precedence: 10

user_schema:
email:
type: String # can be String, Number, DateTime, or Boolean.
mutable: true # defines whether user attribute value can be changed
required: true
name:
type: String
mutable: true
required: true

### Apart from these 2 attributes, CognitoDefaults will be added, and they include
### these attributes are also included in defaults, but in order to override mutable/required properties
### they are also explicitly included here

### Specifying any clients under clients key will render default_client unused
clients:
# client1:
# name: my_client
# # check default_client for configuration values

### Specifying any groups under groups key will render default_user_group unused
groups:
# group1:
# name: usergroup
# description: This group gives access to X


ccr:
custom_policies:
cognito:
action:
- cognito-idp:*
roles:
cognito:
policies_inline:
- cloudwatch-logs
- cognito
functions:
ccrCognitoUPC:
role: cognito
code: https://github.com/base2Services/cloudformation-custom-resources-nodejs/releases/download/1.0.0/ccr-nodejs-1.0.0.zip
runtime: nodejs6.10
named: false
timeout: 30
handler: cognito-user-pool-client/index.handler
ccrCognitoDN:
role: cognito
code: https://github.com/base2Services/cloudformation-custom-resources-nodejs/releases/download/1.0.0/ccr-nodejs-1.0.0.zip
runtime: nodejs6.10
named: false
timeout: 30
handler: cognito-user-pool-domain/index.handler

0 comments on commit 98aa83d

Please sign in to comment.