Los permisos y la AWS CDK - AWS Cloud Development Kit (AWS CDK) v2

Esta es la guía para AWS CDK desarrolladores de la versión 2. La CDK versión anterior entró en mantenimiento el 1 de junio de 2022 y finalizó el soporte el 1 de junio de 2023.

Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.

Los permisos y la AWS CDK

La biblioteca AWS Construct utiliza algunos modismos comunes y ampliamente implementados para administrar el acceso y los permisos. El IAM módulo le proporciona las herramientas que necesita para usar estos modismos.

AWS CDK utiliza AWS CloudFormation para implementar cambios. Cada implementación involucra a un actor (ya sea un desarrollador o un sistema automatizado) que inicia una AWS CloudFormation implementación. Al hacerlo, el actor asumirá una o más IAM identidades (usuario o roles) y, opcionalmente, pasará un rol a AWS CloudFormation.

Si lo utilizas AWS IAM Identity Center para autenticarte como usuario, el proveedor de inicio de sesión único proporciona credenciales de sesión de corta duración que te autorizan a actuar como un rol predefinido. IAM Para obtener información sobre cómo AWS CDK obtiene las AWS credenciales de la autenticación de IAM Identity Center, consulte Descripción de la autenticación de IAMIdentity Center en la Guía de referencia de herramientas y herramientas.AWS SDKs

Entidades principales

Un IAM principal es una AWS entidad autenticada que representa a un usuario, servicio o aplicación a la que puede llamar. AWS APIs La biblioteca AWS Construct permite especificar los directores de varias formas flexibles para permitirles acceder a sus AWS recursos.

En contextos de seguridad, el término «principal» se refiere específicamente a las entidades autenticadas, como los usuarios. Los objetos, como los grupos y las funciones, no representan a los usuarios (ni a otras entidades autenticadas), sino que los identifican indirectamente con el fin de conceder permisos.

Por ejemplo, si creas un IAM grupo, puedes conceder al grupo (y, por tanto, a sus miembros) acceso de escritura a una RDS tabla de Amazon. Sin embargo, el grupo en sí no es un principal porque no representa a una sola entidad (además, no puedes iniciar sesión en un grupo).

En CDK la IAM biblioteca, las clases que identifican directa o indirectamente a los principales implementan la IPrincipalinterfaz, lo que permite que estos objetos se usen indistintamente en las políticas de acceso. Sin embargo, no todos son principales en el sentido de la seguridad. Estos objetos incluyen:

  1. IAMrecursos como RoleUser, y Group

  2. Principios de servicio () new iam.ServicePrincipal('service.amazonaws.com')

  3. Directores federados () new iam.FederatedPrincipal('cognito-identity.amazonaws.com')

  4. Responsables de cuentas (new iam.AccountPrincipal('0123456789012'))

  5. Principales de usuario canónicos () new iam.CanonicalUserPrincipal('79a59d[...]7ef2be')

  6. AWS Organizations directores () new iam.OrganizationPrincipal('org-id')

  7. ARNPrincipios arbitrarios () new iam.ArnPrincipal(res.arn)

  8. Y iam.CompositePrincipal(principal1, principal2, ...) confiar en varios directores

Concesiones

Cada construcción que representa un recurso al que se puede acceder, como un bucket de Amazon S3 o una tabla de Amazon DynamoDB, tiene métodos que conceden acceso a otra entidad. Todos estos métodos tienen nombres que comienzan por grant.

Por ejemplo, los buckets de Amazon S3 tienen los métodos grantRead y grantReadWrite (Python:grant_read,grant_read_write) para permitir el acceso de lectura y lectura/escritura, respectivamente, desde una entidad al bucket. La entidad no necesita saber exactamente qué IAM permisos de Amazon S3 son necesarios para realizar estas operaciones.

El primer argumento de un método de concesión es siempre el tipo IGrantable. Esta interfaz representa las entidades a las que se les pueden conceder permisos. Es decir, representa los recursos con funciones, como los IAM objetos RoleUser, yGroup.

También se pueden conceder permisos a otras entidades. Por ejemplo, más adelante en este tema, mostraremos cómo conceder a un CodeBuild proyecto acceso a un bucket de Amazon S3. Por lo general, el rol asociado se obtiene a través de una role propiedad de la entidad a la que se concede el acceso.

Los recursos que utilizan funciones de ejecución, por ejemplolambda.Function, también se implementanIGrantable, por lo que puedes concederles acceso directamente en lugar de concederles acceso a su función. Por ejemplo, si bucket es un bucket de Amazon S3 y function es una función Lambda, el siguiente código concede a la función acceso de lectura al bucket.

TypeScript
bucket.grantRead(function);
JavaScript
bucket.grantRead(function);
Python
bucket.grant_read(function)
Java
bucket.grantRead(function);
C#
bucket.GrantRead(function);

A veces, los permisos se deben aplicar mientras se implementa la pila. Uno de estos casos es cuando concedes a un recurso AWS CloudFormation personalizado acceso a otro recurso. El recurso personalizado se invocará durante la implementación, por lo que debe tener los permisos especificados en el momento de la implementación.

Otro caso es cuando un servicio verifica que la función que se le transfiere tiene aplicadas las políticas correctas. (Varios AWS servicios lo hacen para asegurarse de que no te olvides de configurar las políticas). En esos casos, la implementación podría fallar si los permisos se aplican demasiado tarde.

Para forzar la aplicación de los permisos de la concesión antes de crear otro recurso, puedes añadir una dependencia a la propia concesión, como se muestra aquí. Si bien el valor devuelto por los métodos de concesión suele descartarse, de hecho, todos los métodos de concesión devuelven un iam.Grant objeto.

TypeScript
const grant = bucket.grantRead(lambda); const custom = new CustomResource(...); custom.node.addDependency(grant);
JavaScript
const grant = bucket.grantRead(lambda); const custom = new CustomResource(...); custom.node.addDependency(grant);
Python
grant = bucket.grant_read(function) custom = CustomResource(...) custom.node.add_dependency(grant)
Java
Grant grant = bucket.grantRead(function); CustomResource custom = new CustomResource(...); custom.node.addDependency(grant);
C#
var grant = bucket.GrantRead(function); var custom = new CustomResource(...); custom.node.AddDependency(grant);

Roles

El IAM paquete contiene una Role construcción que representa IAM los roles. El siguiente código crea un nuevo rol, de confianza en el EC2 servicio de Amazon.

TypeScript
import * as iam from 'aws-cdk-lib/aws-iam'; const role = new iam.Role(this, 'Role', { assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com'), // required });
JavaScript
const iam = require('aws-cdk-lib/aws-iam'); const role = new iam.Role(this, 'Role', { assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com') // required });
Python
import aws_cdk.aws_iam as iam role = iam.Role(self, "Role", assumed_by=iam.ServicePrincipal("ec2.amazonaws.com")) # required
Java
import software.amazon.awscdk.services.iam.Role; import software.amazon.awscdk.services.iam.ServicePrincipal; Role role = Role.Builder.create(this, "Role") .assumedBy(new ServicePrincipal("ec2.amazonaws.com")).build();
C#
using Amazon.CDK.AWS.IAM; var role = new Role(this, "Role", new RoleProps { AssumedBy = new ServicePrincipal("ec2.amazonaws.com"), // required });

Puede agregar permisos a un rol llamando al addToPolicy método del rol (Python:add_to_policy) y pasando una PolicyStatement que defina la regla que se va a agregar. La declaración se agrega a la política predeterminada del rol; si no tiene ninguna, se crea una.

El siguiente ejemplo agrega una declaración de Deny política al rol para las acciones ec2:SomeAction y s3:AnotherAction los recursos bucket y otherRole (Python:other_role), con la condición de que el servicio autorizado lo sea AWS CodeBuild.

TypeScript
role.addToPolicy(new iam.PolicyStatement({ effect: iam.Effect.DENY, resources: [bucket.bucketArn, otherRole.roleArn], actions: ['ec2:SomeAction', 's3:AnotherAction'], conditions: {StringEquals: { 'ec2:AuthorizedService': 'codebuild.amazonaws.com', }}}));
JavaScript
role.addToPolicy(new iam.PolicyStatement({ effect: iam.Effect.DENY, resources: [bucket.bucketArn, otherRole.roleArn], actions: ['ec2:SomeAction', 's3:AnotherAction'], conditions: {StringEquals: { 'ec2:AuthorizedService': 'codebuild.amazonaws.com' }}}));
Python
role.add_to_policy(iam.PolicyStatement( effect=iam.Effect.DENY, resources=[bucket.bucket_arn, other_role.role_arn], actions=["ec2:SomeAction", "s3:AnotherAction"], conditions={"StringEquals": { "ec2:AuthorizedService": "codebuild.amazonaws.com"}} ))
Java
role.addToPolicy(PolicyStatement.Builder.create() .effect(Effect.DENY) .resources(Arrays.asList(bucket.getBucketArn(), otherRole.getRoleArn())) .actions(Arrays.asList("ec2:SomeAction", "s3:AnotherAction")) .conditions(java.util.Map.of( // Map.of requires Java 9 or later "StringEquals", java.util.Map.of( "ec2:AuthorizedService", "codebuild.amazonaws.com"))) .build());
C#
role.AddToPolicy(new PolicyStatement(new PolicyStatementProps { Effect = Effect.DENY, Resources = new string[] { bucket.BucketArn, otherRole.RoleArn }, Actions = new string[] { "ec2:SomeAction", "s3:AnotherAction" }, Conditions = new Dictionary<string, object> { ["StringEquals"] = new Dictionary<string, string> { ["ec2:AuthorizedService"] = "codebuild.amazonaws.com" } } }));

En el ejemplo anterior, hemos creado una nueva PolicyStatement línea con la llamada addToPolicy (Python:add_to_policy). También puedes incluir una declaración de política existente o una que hayas modificado. El PolicyStatementobjeto tiene numerosos métodos para añadir principios, recursos, condiciones y acciones.

Si utiliza una construcción que requiere un rol para funcionar correctamente, puede realizar una de las siguientes acciones:

  • Transfiere un rol existente al crear una instancia del objeto de construcción.

  • Deje que la construcción cree un nuevo rol para usted, confiando en el director de servicio apropiado. En el ejemplo siguiente se utiliza una construcción de este tipo: un CodeBuild proyecto.

TypeScript
import * as codebuild from 'aws-cdk-lib/aws-codebuild'; // imagine roleOrUndefined is a function that might return a Role object // under some conditions, and undefined under other conditions const someRole: iam.IRole | undefined = roleOrUndefined(); const project = new codebuild.Project(this, 'Project', { // if someRole is undefined, the Project creates a new default role, // trusting the codebuild.amazonaws.com service principal role: someRole, });
JavaScript
const codebuild = require('aws-cdk-lib/aws-codebuild'); // imagine roleOrUndefined is a function that might return a Role object // under some conditions, and undefined under other conditions const someRole = roleOrUndefined(); const project = new codebuild.Project(this, 'Project', { // if someRole is undefined, the Project creates a new default role, // trusting the codebuild.amazonaws.com service principal role: someRole });
Python
import aws_cdk.aws_codebuild as codebuild # imagine role_or_none is a function that might return a Role object # under some conditions, and None under other conditions some_role = role_or_none(); project = codebuild.Project(self, "Project", # if role is None, the Project creates a new default role, # trusting the codebuild.amazonaws.com service principal role=some_role)
Java
import software.amazon.awscdk.services.iam.Role; import software.amazon.awscdk.services.codebuild.Project; // imagine roleOrNull is a function that might return a Role object // under some conditions, and null under other conditions Role someRole = roleOrNull(); // if someRole is null, the Project creates a new default role, // trusting the codebuild.amazonaws.com service principal Project project = Project.Builder.create(this, "Project") .role(someRole).build();
C#
using Amazon.CDK.AWS.CodeBuild; // imagine roleOrNull is a function that might return a Role object // under some conditions, and null under other conditions var someRole = roleOrNull(); // if someRole is null, the Project creates a new default role, // trusting the codebuild.amazonaws.com service principal var project = new Project(this, "Project", new ProjectProps { Role = someRole });

Una vez creado el objeto, el rol (ya sea el rol transferido o el predeterminado creado por la construcción) está disponible como propiedadrole. Sin embargo, esta propiedad no está disponible en los recursos externos. Por lo tanto, estas construcciones tienen un método addToRolePolicy (Python:add_to_role_policy).

El método no hace nada si la construcción es un recurso externo y, de lo contrario, llama al método addToPolicy (Python:add_to_policy) de la role propiedad. Esto le ahorra la molestia de tratar el caso indefinido de forma explícita.

El siguiente ejemplo demuestra lo siguiente:

TypeScript
// project is imported into the CDK application const project = codebuild.Project.fromProjectName(this, 'Project', 'ProjectName'); // project is imported, so project.role is undefined, and this call has no effect project.addToRolePolicy(new iam.PolicyStatement({ effect: iam.Effect.ALLOW, // ... and so on defining the policy }));
JavaScript
// project is imported into the CDK application const project = codebuild.Project.fromProjectName(this, 'Project', 'ProjectName'); // project is imported, so project.role is undefined, and this call has no effect project.addToRolePolicy(new iam.PolicyStatement({ effect: iam.Effect.ALLOW // ... and so on defining the policy }));
Python
# project is imported into the CDK application project = codebuild.Project.from_project_name(self, 'Project', 'ProjectName') # project is imported, so project.role is undefined, and this call has no effect project.add_to_role_policy(iam.PolicyStatement( effect=iam.Effect.ALLOW, # ... and so on defining the policy )
Java
// project is imported into the CDK application Project project = Project.fromProjectName(this, "Project", "ProjectName"); // project is imported, so project.getRole() is null, and this call has no effect project.addToRolePolicy(PolicyStatement.Builder.create() .effect(Effect.ALLOW) // .. and so on defining the policy .build();
C#
// project is imported into the CDK application var project = Project.FromProjectName(this, "Project", "ProjectName"); // project is imported, so project.role is null, and this call has no effect project.AddToRolePolicy(new PolicyStatement(new PolicyStatementProps { Effect = Effect.ALLOW, // ... and so on defining the policy }));

Políticas de recursos

Algunos recursos AWS, como los buckets y las IAM funciones de Amazon S3, también tienen una política de recursos. Estas construcciones tienen un addToResourcePolicy método (Python:add_to_resource_policy), que toma a PolicyStatement como argumento. Cada declaración de política agregada a una política de recursos debe especificar al menos un principal.

En el siguiente ejemplo, el bucket de Amazon S3 se bucket otorga un rol con el s3:SomeAction permiso para sí mismo.

TypeScript
bucket.addToResourcePolicy(new iam.PolicyStatement({ effect: iam.Effect.ALLOW, actions: ['s3:SomeAction'], resources: [bucket.bucketArn], principals: [role] }));
JavaScript
bucket.addToResourcePolicy(new iam.PolicyStatement({ effect: iam.Effect.ALLOW, actions: ['s3:SomeAction'], resources: [bucket.bucketArn], principals: [role] }));
Python
bucket.add_to_resource_policy(iam.PolicyStatement( effect=iam.Effect.ALLOW, actions=["s3:SomeAction"], resources=[bucket.bucket_arn], principals=role))
Java
bucket.addToResourcePolicy(PolicyStatement.Builder.create() .effect(Effect.ALLOW) .actions(Arrays.asList("s3:SomeAction")) .resources(Arrays.asList(bucket.getBucketArn())) .principals(Arrays.asList(role)) .build());
C#
bucket.AddToResourcePolicy(new PolicyStatement(new PolicyStatementProps { Effect = Effect.ALLOW, Actions = new string[] { "s3:SomeAction" }, Resources = new string[] { bucket.BucketArn }, Principals = new IPrincipal[] { role } }));

Uso de IAM objetos externos

Si has definido un IAM usuario, director, grupo o rol fuera de AWS CDK la aplicación, puedes usar ese IAM objeto en AWS CDK la aplicación. Para ello, crea una referencia al mismo con su ARN nombre. (Use el nombre para los usuarios, grupos y roles). Luego, la referencia devuelta se puede usar para conceder permisos o para elaborar declaraciones de políticas, como se explicó anteriormente.

Las políticas (incluidas las políticas gestionadas) se pueden utilizar de forma similar mediante los siguientes métodos. Puede utilizar las referencias a estos objetos en cualquier lugar donde se requiera una IAM política.

nota

Como ocurre con todas las referencias a AWS recursos externos, no puedes modificar IAM objetos externos en tu CDK aplicación.