Funções e políticas para AWS com Serverless Framework
As políticas são um elemento da Amazon Web Services (AWS) associado a uma identidade, um serviço, etc., onde podemos configurar as ações que pode realizar em um ou mais recursos. Estas políticas não podem ser atribuídas diretamente a um serviço AWS (Lambda, EC3, Glue, etc.), mas requerem um intermediário que, neste caso, é a função.
As funções são uma parte fundamental da AWS, pois as usamos para controlar as ações que um usuário ou outro serviço pode realizar. As funções são criadas para uma conta e podem ser utilizadas em diferentes regiões (tendo em conta a estrutura dos recursos em cada política atribuída à função), sendo geridas através do portal Identity and Access Management (IAM).
Existem diferentes ações que nos permitem executar políticas e funções. Eles estão entre eles:
- Delegação de permissão: As funções permitem atribuir permissões específicas a serviços ou usuários sem precisar compartilhar credenciais. Isto é especialmente útil em cenários onde é necessário conceder acesso temporário a recursos específicos.
- Acesso a serviços: As funções podem ser assumidas por serviços e aplicativos em execução no ambiente AWS. Isso permite que os aplicativos acessem outros serviços sem a necessidade de armazenar credenciais diretamente no código.
- Acesso Transitório: As funções podem ser usadas para fornecer acesso temporário a usuários ou serviços, gerando credenciais temporárias (tokens) que possuem um período de validade definido.
- Confiança entre contas (Cross over account): As funções também podem ser usadas para estabelecer relações de confiança entre contas da AWS, permitindo que recursos de uma conta sejam acessíveis por entidades de outras contas.
Para obter mais informações sobre políticas e permissões no IAM, consulte a documentação oficial aqui.
Importante: Todos os serviços na AWS nascem sem permissões (políticas), portanto é possível definir uma função criada previamente e com as permissões necessárias para que funcione corretamente.
Exemplo 1: O usuário tem uma função associada que pode listar os buckets existentes no S3. Se o usuário quiser criar um novo bucket, o console AWS mostrará um aviso de que ele não tem as permissões necessárias para criar um bucket.
Exemplo 2: Temos um serviço (Lambda) que precisa criar e ler registros de um banco de dados no DynamoDB. Caso o Lambda tente atualizar ou excluir, você receberá um erro.
Uma das boas práticas na hora de criar funções e políticas é dar a permissão mínima, para que a nossa função só possa realizar as tarefas realmente necessárias para o bom funcionamento do nosso serviço, evitando uma escalada de ações que prejudiquem a segurança dos nossos serviços. AWS Well-Architect (“O bom arquiteto da AWS”) é um guia com diretrizes para que nosso ecossistema AWS tenha as melhores práticas em segurança e escalabilidade.
Criação de políticas
Diante do exposto, é hora de iniciar o processo onde criaremos uma política de acesso a um bucket S3 e outra que permita inserir e obter elementos do Dynamo. Ambos serão aplicados a um Lambda.
Usaremos o CloudFormation para criar nossas políticas e funções, evitando o uso do console AWS.
Estrutura de uma política
Nome da nossa política: Nomenclatura que nossa política terá dentro do nosso serverless e como nos referiremos a ela em outros arquivos.
Type: O tipo de recurso, como uma política gerenciada pelo AWS IAM, que será AWS::IAM::ManagedPolicy.
Properties: Nesta seção definiremos os atributos necessários para que nossa política possa ser criada.
ManagedPolicyName: O nome exclusivo da nossa política no IAM. Será aquele que veremos na função ao usar o console AWS. Da mesma forma, será o nome com o qual nosso ARN (Amazon Resource Name).
Description: Opcional, descreva o que e por que é uma política.
Path: Definimos o local onde nossa política será armazenada. Geralmente o caminho raiz.
PolicyDocument: Definiremos o documento de política que detalha as permissões concedidas, que se tornará o bloco de código JavaScript que vemos no console.
Version: A versão da estrutura política.
Statement: Define as permissões da política.
Effect: Definimos se a política permite ou proíbe uma ação.
Action: Especificaremos as ações permitidas ou proibidas.
Resource: Listamos os recursos aos quais esta política se aplica.
Política para acessar objetos em um bucket (arquivopolicies.yml)
Resources:
DemoListoProEdSantosHnPolicy:
Type: AWS::IAM::ManagedPolicy
Properties:
ManagedPolicyName: DemoListoProEdSantosHnPolicy
Description: Permite que nuestra lambda acceda a objetos en un bucket S3.
Path: "/"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- s3:GetObject
Resource:
- arn:aws:s3:::nombre-de-nuestro-bucket/*
- arn:aws:s3:::nombre-de-nuestro-bucket
OBS: Com esta política, nosso papel poderá obter (get) objetos que estão dentro do nosso bucket “nome-do-nosso-bucket”, mas você não poderá listar, fazer upload, excluir, atualizar objetos ou gerar uma url pré-assinada, etc.
Política para inserir e obter registros de uma tabela do Dynamo (arquivo policies.yml)
Resources:
DemoListoProEdSantosHnPolicy:
…
…
DemoListoProEdSantosHnDynamoPolicy:
Type: AWS::IAM::ManagedPolicy
Properties:
ManagedPolicyName: DemoListoProEdSantosHnDynamoPolicy
Description: Permite que nuestra lambda Inserte y obtenga registros de Dynamo.
Path: "/"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- dynamodb:BatchGetItem
- dynamodb:GetItem
- dynamodb:Query
- dynamodb:Scan
- dynamodb:BatchWriteItem
- dynamodb:PutItem
Resource: "arn:aws:dynamodb:{region}:{account_id}:table/ListoProTable"
OBS: Com esta política, nossa função poderá obter um registro, um lote de registros (limitado pela nossa configuração do Dynamo), pesquisar registros, inserir um registro ou inserir vários registros. Na seção Resource devemos adicionar a região e o ID da nossa conta onde a tabela do Dynamo está localizada.
Se tivermos um ambiente de desenvolvimento em uma região e nosso ambiente de produção em outra e em ambas as regiões nosso recurso tiver o mesmo nome, devemos considerar não deixar a região explicitamente em nosso yml. Recomenda-se usar um * em vez da nossa região. Desta forma, a nossa política será aplicada a todas as regiões.
Resource: "arn:aws:dynamodb:*:{account_id}:table/ListoProTable"
Criação de função
Depois de criarmos as políticas que permitem que nosso Lambda acesse um bucket S3 e uma tabela Dynamo, podemos criar nossa função à qual nosso Lambda será atribuído.
Estrutura de uma função
Nome da nossa função: Corresponde ao nome que nossa função terá dentro do nosso serverless e como nos referiremos a ela em outros arquivos.
Type: O tipo de recurso como uma política gerenciada pelo AWS IAM, que será AWS::IAM::Role.
Properties: Nesta seção definiremos os atributos necessários para que nossa função possa ser criada.
RoleName: Nosso nome exclusivo no IAM será o nome que podemos pesquisar para atribuir a um serviço na AWS. Da mesma forma, o nome com o qual nosso RNA será composto.
MaxSessionDuration: Define a duração máxima de uma sessão assumida por esta função. Pelo menos é uma hora ou 3600 segundos.
AssumeRolePolicyDocument: Define o documento que controla quem pode assumir esta função.
Statement: Define as políticas dentro do documento.
Effect: Define se a política permite ou proíbe uma ação.
Principal: Especifica o principal que tem permissão para assumir essa função.
Action: Especificamos a ação permitida.
ManagedPolicyArns: Listamos os ARNs de política que a função terá.
Criação de função (roles.yml file)
Resources:
DemoListoProEdSantoHnRol:
Type: AWS::IAM::Role
Properties:
RoleName: DemoListoProEdSantoHnRol
MaxSessionDuration: 3600
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action:
- sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
- Ref: DemoListoProEdSantosHnPolicy
- Ref: DemoListoProEdSantosHnDynamoPolicy
Principal: Nosso papel pode ser assumido pelo serviço Lambda.
Action: Especificamos que um serviço (definido no principal) pode usar esta função.
ManagedPolicyArns: Especificamos as três políticas que usaremos:
- AWSLambdaBasicExecutionRole: É uma política fornecida pela AWS que fornece permissões básicas para nosso Lambda gravar logs e outras permissões essenciais.
- Ref: DemoListoProEdSantosHnPolicy: refere-se à nossa política definida anteriormente em policies.yml. O Serverless Framework converterá os arquivos individuais em um arquivo para ser enviado à AWS.
- Ref: DemoListoProEdSantosHnDynamoPolicy: Semelhante ao anterior.
Para implantar nossas funções e permissões com o Serverless Framework, devemos criar nosso arquivo serverless.yml (semelhante ao arquivo que cria a seção abaixo).
Serverless.yml
service: nombre-de-proyecto-iam
provider:
name: aws
runtime: python3.8
stage: ${self:custom.stage, 'dev'}
region: ${self:custom.config.${self:custom.stage}.my-region}
custom:
stage: ${opt:stage, 'dev'}
config:
dev:
account_id: ''
my-region: ${opt:region, 'us-east-2'}
prd:
account_id: ''
my-region: ${opt:region, 'us-east-1'}
resources:
- ${file(policies.yml)}
- ${file(roles.yml)}
Para finalizar basta escrever o comando serverless deploy na pasta onde nosso arquivo serverless.yml está localizado. Com isso criamos as políticas e a função necessária para o nosso Lambda.
O código mostrado neste artigo pode ser baixado no seguinte repositório: https://github.com/edsantoshn/aws-posts
Em resumo, a criação de políticas e funções na AWS por meio do CloudFormation e do Serverless Framework oferece uma abordagem robusta e segura para gerenciar permissões.
Seguindo boas práticas de concessão de permissões mínimas, controle de acesso e confiança na documentação oficial, podemos garantir um ambiente de nuvem confiável e escalável.
A Revelo Content Network acolhe todas as raças, etnias, nacionalidades, credos, gêneros, orientações, pontos de vista e ideologias, desde que promovam diversidade, equidade, inclusão e crescimento na carreira dos profissionais de tecnologia.