AWS CDK用户池授权者

时间:2018-10-09 18:03:52

标签: aws-sdk amazon-cognito aws-cdk

我正在尝试使用AWS-CDK创建API网关,并使用Cognito用户池授权者保护REST端点。

我找不到任何例子。我认为应该看起来像这样,但是也许我不需要的方法不存在?

const cdk       = require('@aws-cdk/cdk');
const lambda    = require('@aws-cdk/aws-lambda');
const apigw     = require('@aws-cdk/aws-apigateway');

const path  = require('path');

// 
// Define the stack:
class MyStack extends cdk.Stack {
    constructor (parent, id, props) {
        super(parent, id, props);    

        var tmethodHandler = new lambda.Function(this, 'test-lambda', {
            runtime: lambda.Runtime.NodeJS810,
            handler: 'index.handler',
            code: lambda.Code.directory( path.join( __dirname, 'lambda')),
        });

        var api         = new apigw.RestApi(this, 'test-api');

        const tmethod   = api.root.addResource('testmethod');

        const tmethodIntegration    = new apigw.LambdaIntegration(tmethodHandler);

        tmethod.addMethod('GET', getSessionIntegration, {
            authorizationType: apigw.AuthorizationType.Cognito,
            authorizerId : 'crap!!!?'
        });

    }
}

class MyApp extends cdk.App {
    constructor (argv) {
        super(argv);

        new MyStack(this, 'test-apigw');
    }
}

console.log(new MyApp(process.argv).run());

7 个答案:

答案 0 :(得分:4)

截至 Auth.auth().signInAnonymously() { (result , error) in guard let authResult = result else { return } let user = authResult.user let isAnonymous = user.isAnonymous // true if(isAnonymous){ let uid = user.uid User.shared.userId = uid print("user id : \(User.shared.userId)") let userRef = db.collection("user").document(User.shared.userId) userRef.getDocument { (querySnapshot, err) in if let err = err { print("Error getting documents: \(err)") } else { if (querySnapshot?.get("progress") == nil) { var dataDict : Dictionary<String , Any> = [:] dataDict["progress"] = 0 userRef.setData(dataDict) }else{ let dict = querySnapshot?.data() let sssresult = dict!.filter{ $0.key == "progress" }.first?.value as? Int ?? 0 User.shared.progress = sssresult } } } } // Do any additional setup after loading the view. } // CocoaPods: try to load from the gRPC-C++ Framework. NSBundle* _Nullable FindGrpcCppFrameworkBundle() { return [NSBundle bundleWithIdentifier:@"org.cocoapods.grpcpp"]; } 为止,@ bgdnip的答案并不完全适用于September 2019。我可以通过以下方式工作:

typescript

这是来自https://docs.aws.amazon.com/cdk/latest/guide/cfn_layer.html#cfn_layer_resource_props

更新十月

以上内容已经过时且不必要,可以通过以下const api = new RestApi(this, 'RestAPI', { restApiName: 'Rest-Name', description: 'API for journey services.', }); const putIntegration = new LambdaIntegration(handler); const auth = new CfnAuthorizer(this, 'APIGatewayAuthorizer', { name: 'customer-authorizer', identitySource: 'method.request.header.Authorization', providerArns: [providerArn.valueAsString], restApiId: api.restApiId, type: AuthorizationType.COGNITO, }); const post = api.root.addMethod('PUT', putIntegration, { authorizationType: AuthorizationType.COGNITO }); const postMethod = post.node.defaultChild as CfnMethod; postMethod.addOverride('Properties.AuthorizerId', { Ref: auth.logicalId });

实现
aws-cdk 1.12.0

答案 1 :(得分:2)

您必须:

  • 创建api网关
  • 在api网关中将Cognito设置为授权者
  • 在您的方法中设置授权
  • 将与lambda的集成设置为“使用Lambda代理集成”。 LambdaIntegration属性默认情况下为true,因此不必担心

最后,发出一个请求,在令牌中添加令牌。 API网关将使用Cognito对其进行验证。如果通过此验证,则将触发您的lambda,并且在事件中您可以找到声明 event.requestContext.authorizer.claims


const lambda = require("@aws-cdk/aws-lambda");
const apiGateway = require('@aws-cdk/aws-apigateway'); 

 const api = new apiGateway.RestApi(
      this,
      '<id-ApiGateway>',
      {
        restApiName: '<ApiGateway-name>',
      },
    );

    const auth = new apiGateway.CfnAuthorizer(this, '<id>', {
      name: "<authorizer-name>",
      type: apiGateway.AuthorizationType.COGNITO,
      authorizerResultTtlInSeconds: 300,
      identitySource: "method.request.header.Authorization",
      restApiId: api.restApiId,
      providerArns: ['<userPool.userPoolArn>'],
    });

    const myLambda= new lambda.Function(this, "<id>", {
      functionName: '<lambda-name>',
      runtime: lambda.Runtime.NODEJS_10_X,
      handler: "<your-handler>",
      code: lambda.Code.fromAsset("<path>"), // TODO: modify the way to get the path
    });

      const lambdaIntegration = new apiGateway.LambdaIntegration(myLambda);

      const resource = api.root.resourceForPath('<your-api-path>');
      // When the API will be deployed, the URL will look like this
      // https://xxxxxx.execute-api.us-east-2.amazonaws.com/dev/<your-api-path>

      const authorizationOptions = {
        apiKeyRequired: false,
        authorizer: {authorizerId: auth.ref},
        authorizationType: 'COGNITO_USER_POOLS'
      };

      resource.addMethod(
        GET, // your method
        lambdaIntegration,
        authorizationOptions
      );

答案 2 :(得分:1)

以前的答案不再起作用,因为authorizerId属性已被authorizer取代,目前还没有完全实现。

相反,可以通过使用基础的CfnResource对象as described in the official guide来完成。

这里以Python代码为例:

from aws_cdk import cdk
from aws_cdk import aws_apigateway


class Stk(cdk.Stack):
    def __init__(self, app, id):
        super().__init__(app, id)

        api_gw = aws_apigateway.RestApi(self, 'MyApp')
        post_method = api_gw.root.add_method(http_method='POST')

        # Create authorizer using low level CfnResource
        api_gw_authorizer = aws_apigateway.CfnAuthorizer(
            scope=self,
            id='my_authorizer',
            rest_api_id=api_gw.rest_api_id,
            name='MyAuth',
            type='COGNITO_USER_POOLS',
            identity_source='method.request.header.name.Authorization',
            provider_arns=[
                'arn:aws:cognito-idp:eu-west-1:123456789012:userpool/'
                'eu-west-1_MyCognito'])

        # Get underlying post_method Resource object. Returns CfnMethod
        post_method_resource = post_method.node.find_child('Resource')
        # Add properties to low level resource
        post_method_resource.add_property_override('AuthorizationType',
                                                   'COGNITO_USER_POOLS')
        # AuthorizedId uses Ref, simulate with a dictionaty
        post_method_resource.add_property_override(
                'AuthorizerId',
                {"Ref": api_gw_authorizer.logical_id})


app = cdk.App()
stk = Stk(app, "myStack")

app.synth()

答案 3 :(得分:1)

对于使用Java版CDK的怪人(像我一样),您可以利用Cfn构造上的二传手:

final UserPool userPool = ...
final RestApi restApi = ...
final LambdaIntegration integration = ...
final Method method = restApi.getRoot().addMethod("GET", integration);

final CfnAuthorizer cognitoAuthorizer = new CfnAuthorizer(this, "CfnCognitoAuthorizer",
        CfnAuthorizerProps.builder()
                .name("CognitoAuthorizer")
                .restApiId(restApi.getRestApiId())
                .type("COGNITO_USER_POOLS")
                .providerArns(Arrays.asList(userPool.getUserPoolArn()))
                .identitySource("method.request.header.Authorization")
                .build());

final CfnMethod cfnMethod = (CfnMethod) method.getNode().getDefaultChild();
cfnMethod.setAuthorizationType("COGNITO_USER_POOLS");
cfnMethod.setAuthorizerId(authorizer.getRef());

答案 4 :(得分:0)

我弄清楚了一种机制……我能够使它像这样工作:

V

现在要弄清楚如何在API Gateway上启用CORS标头...

答案 5 :(得分:0)

的确。没有通过复制和粘贴来执行此操作的示例;)。这是我的示例,用于创建AWS cognito用户池,并使用基于Java的AWS CDK(版本为0.24.1)将用户pol授权者与API网关和lambda函数连接。

该示例仅是为名为“ Foo”的功能提供受保护的API的示例。

  • 认知用户池
  • API网关
  • Lambda
  • DynamoDB

    // -----------------------------------------------------------------------
    // Cognito User Pool
    // -----------------------------------------------------------------------
    CfnUserPool userPool = new CfnUserPool(this, "cognito",
        CfnUserPoolProps.builder()
            .withAdminCreateUserConfig(
                AdminCreateUserConfigProperty.builder()
                    .withAllowAdminCreateUserOnly(false)
                    .build())
            .withPolicies(
                PoliciesProperty.builder()
                    .withPasswordPolicy(
                        PasswordPolicyProperty.builder()
                            .withMinimumLength(6)
                            .withRequireLowercase(false)
                            .withRequireNumbers(false)
                            .withRequireSymbols(false)
                            .withRequireUppercase(false)
                            .build()
                    )
                    .build()
            )
            .withAutoVerifiedAttributes(Arrays.asList("email"))
            .withSchema(Arrays.asList(
                CfnUserPool.SchemaAttributeProperty.builder()
                    .withAttributeDataType("String")
                    .withName("email")
                    .withRequired(true)
                    .build()))
            .build());
    
    // -----------------------------------------------------------------------
    // Cognito User Pool Client
    // -----------------------------------------------------------------------
    new CfnUserPoolClient(this, "cognitoClient",
        CfnUserPoolClientProps.builder()
            .withClientName("UserPool")
            .withExplicitAuthFlows(Arrays.asList("ADMIN_NO_SRP_AUTH"))
            .withRefreshTokenValidity(90)
            .withUserPoolId(userPool.getRef())
            .build());
    
    // -----------------------------------------------------------------------
    // Lambda function
    // -----------------------------------------------------------------------
    Function function = new Function(this, "function.foo",
        FunctionProps.builder()
            // lamda code located in /functions/foo
            .withCode(Code.asset("functions/foo"))
            .withHandler("index.handler")
            .withRuntime(Runtime.NODE_J_S810)
            .build());
    
    // -----------------------------------------------------------------------
    // DynamoDB Table
    // -----------------------------------------------------------------------
    Table table = new Table(this, "dynamodb.foo", TableProps.builder()
        .withTableName("foo")
        .withPartitionKey(Attribute.builder()
            .withName("id")
            .withType(AttributeType.String)
            .build())
        .build());
    
    // GRANTS function -> table
    table.grantReadWriteData(function.getRole());
    
    // -----------------------------------------------------------------------
    // API Gateway
    // -----------------------------------------------------------------------
    
    // API Gateway REST API with lambda integration
    LambdaIntegration lambdaIntegration = new LambdaIntegration(function);
    RestApi restApi = new RestApi(this, "foo");
    
    // Authorizer configured with cognito user pool
    CfnAuthorizer authorizer = new CfnAuthorizer(this, "authorizer",
        CfnAuthorizerProps.builder()
            .withName("cognitoAuthorizer")
            .withRestApiId(restApi.getRestApiId())
            .withIdentitySource("method.request.header.Authorization")
            .withProviderArns(Arrays.asList(userPool.getUserPoolArn()))
            .withType("COGNITO_USER_POOLS")
            .build());
    
    // Bind authorizer to API ressource
    restApi.getRoot().addMethod("ANY", lambdaIntegration, MethodOptions
        .builder()
          .withAuthorizationType(AuthorizationType.Cognito)
          .withAuthorizerId(authorizer.getAuthorizerId())
        .build());
    

答案 6 :(得分:0)

这是我在TypeScript中的解决方案(基于bgdnlp的响应)

import { App, Stack, Aws } from '@aws-cdk/core';
import { Code, Function, Runtime } from '@aws-cdk/aws-lambda';
import { LambdaIntegration, RestApi, CfnAuthorizer, CfnMethod } from '@aws-cdk/aws-apigateway';

const app = new App();
const stack = new Stack(app, `mystack`);
const api = new RestApi(stack, `myapi`);

const region = Aws.REGION;
const account = Aws.ACCOUNT_ID;
const cognitoArn = `arn:aws:cognito-idp:${region}:${account}:userpool/${USER_POOL_ID}`;

const authorizer = new CfnAuthorizer(stack, 'Authorizer', {
  name: `myauthorizer`,
  restApiId: api.restApiId,
  type: 'COGNITO_USER_POOLS',
  identitySource: 'method.request.header.Authorization',
  providerArns: [cognitoArn],
});

const lambda = new Function(stack, 'mylambda', {
  runtime: Runtime.NODEJS_10_X,
  code: Code.asset('dist'),
  handler: `index.handler`,
});

const integration = new LambdaIntegration(lambda);

const res = api.root.addResource('hello');

const method = res.addMethod('GET', integration);

const child = method.node.findChild('Resource') as CfnMethod;

child.addPropertyOverride('AuthorizationType', 'COGNITO_USER_POOLS');

child.addPropertyOverride('AuthorizerId', { Ref: authorizer.logicalId });