Preparar AWS para cosigner

Esta seção mostra o que precisa estar pronto na AWS antes da instalação do cosigner. Ela descreve os recursos necessários e como eles se encaixam no modelo da Hotwallets.

Antes de instalar o cosigner, a AWS precisa estar preparada com os recursos corretos.

Arquitetura dos cosigners na AWS

Antes de comecar

Antes de iniciar esta etapa, confirme:

  • voce tem acesso ao console da AWS;
  • voce consegue criar IAM Role, bucket S3, chave KMS e EC2;
  • a regiao da AWS onde o cosigner sera instalado esta definida;
  • voce sabe quantos cosigners serao usados no ambiente.

Regras da Hotwallets para esta etapa

Hoje o cosigner da Hotwallets segue estas regras:

  • suporte somente em AWS Nitro Enclaves;
  • operacao com no minimo 2 cosigners;
  • cada cosigner deve ter seu proprio conjunto de recursos.

Isso significa que a preparacao abaixo precisa ser repetida para cada cosigner.

O que sera criado para cada cosigner

Para cada cosigner, prepare:

  1. uma IAM Role;
  2. um bucket S3;
  3. uma KMS Customer Managed Key (CMK);
  4. uma policy adicional na IAM Role;
  5. uma EC2 compativel com Nitro Enclaves.

Informacoes que voce vai precisar anotar

Ao longo da configuracao, anote estes valores:

  • nome da IAM Role;
  • IAM ARN da role criada;
  • nome do bucket;
  • Bucket ARN;
  • KMS ARN;
  • ID da conta AWS;
  • regiao da AWS;
  • nome da EC2 criada.

Sem esses valores, a configuracao das policies seguintes fica incompleta.

Como usar esta secao

Execute um passo por vez e so avance quando o resultado esperado daquele passo estiver confirmado.

Se algum recurso nao puder ser criado ou se algum valor nao puder ser copiado ao final do passo, interrompa o processo e corrija o problema antes de seguir.

Passo 1: criar a IAM Role

A IAM Role liga a instancia EC2 aos recursos usados pelo cosigner.

No console da AWS:

  1. abra IAM;
  2. entre em Roles;
  3. clique em Create role;
  4. em Trusted entity type, escolha AWS service;
  5. em Service or use case, escolha EC2;
  6. clique em Next;
  7. em Add permissions, nao selecione nada ainda;
  8. clique em Next;
  9. defina um nome para a role, por exemplo hotwallets-cosigner-1-role;
  10. crie a role sem alterar a trust policy.

O que copiar ao final deste passo

Copie o IAM ARN.

Formato:

arn:aws:iam::{ACCOUNT-ID}:role/{ROLE-NAME}

Exemplo:

arn:aws:iam::123456789012:role/hotwallets-cosigner-1-role

Resultado esperado

Ao final desse passo, a role existe e a secao Permissions policies ainda esta vazia. Isso e esperado.

Passo 2: criar o bucket S3

O bucket S3 sera usado como persistencia do cosigner.

No console da AWS:

  1. abra Amazon S3;
  2. clique em Create bucket;
  3. informe o nome do bucket;
  4. mantenha o restante como padrao, salvo exigencia do ambiente;
  5. crie o bucket;
  6. abra o bucket criado;
  7. entre em Permissions;
  8. na secao Bucket policy, clique em Edit;
  9. cole a policy abaixo;
  10. clique em Save changes.

Exemplo de nome:

hotwallets-cosigner-1-storage

Ajustes necessarios na policy

Troque:

  • {BUCKET-NAME} pelo nome real do bucket;
  • {ACCOUNT-ID} pelo ID da conta AWS;
  • {ROLE-NAME} pelo nome da role criada no passo anterior.
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Deny",
      "Principal": "*",
      "Action": [
        "s3:PutObject",
        "s3:GetObject",
        "s3:DeleteObject",
        "s3:ListBucket",
        "s3:ListBucketMultipartUploads",
        "s3:AbortMultipartUpload",
        "s3:GetObjectAcl",
        "s3:PutObjectAcl",
        "s3:RestoreObject"
      ],
      "Resource": [
        "arn:aws:s3:::{BUCKET-NAME}",
        "arn:aws:s3:::{BUCKET-NAME}/*"
      ],
      "Condition": {
        "ArnNotEquals": {
          "aws:PrincipalArn": "arn:aws:iam::{ACCOUNT-ID}:role/{ROLE-NAME}"
        }
      }
    }
  ]
}

O que copiar ao final deste passo

Copie o Bucket ARN.

Formato:

arn:aws:s3:::{BUCKET-NAME}

Exemplo:

arn:aws:s3:::hotwallets-cosigner-1-storage

Resultado esperado

Ao final desse passo, o bucket existe e a bucket policy foi salva sem erro.

Passo 3: criar a chave KMS

A chave KMS protege o material sensivel usado pelo cosigner.

No console da AWS:

  1. abra AWS KMS;
  2. clique em Create key;
  3. em Key type, escolha Symmetric;
  4. em Key usage, escolha Encrypt and decrypt;
  5. abra Advanced options;
  6. em Key material origin, escolha KMS;
  7. em Regionality, escolha Single-Region key;
  8. clique em Next.

Use Multi-Region key somente se a EC2 estiver em outra regiao.

Labels da chave

Na tela Add labels:

  • em Alias, defina algo como hotwallets-cosigner-1;
  • opcionalmente preencha Description e Tags;
  • clique em Next.

Permissoes da chave

Na tela Define key administrative permissions:

  • deixe Key administrators em branco;
  • mantenha a opcao de Key deletion marcada;
  • clique em Next.

Na tela Define key usage permissions:

  • deixe Key users em branco;
  • clique em Next.

Ajustes necessarios na key policy

Na tela Review:

  1. role ate a secao Key policy;
  2. cole a policy abaixo;
  3. clique em Finish.

Troque:

  • {ACCOUNT-ID} pelo ID da conta;
  • {ROLE-NAME} pelo nome da IAM Role;
  • {PCR8-VALUE} pelo valor correspondente ao ambiente.

Valores de PCR8

Use o valor correto para o ambiente:

  • Global: da1d9eca20ce98ab4fdbc51f8e5a2307fd4c61829b7d8bff40976cd6676862c8f3476ff4bdd0f65ecf4a48d6eb3099a8
  • Europe: fffc94d68a150b49dc39b23954c793cd1a4f7972f528a1ee258dc130b6cd9454e29ae72ef66bd9697a55e774e17a2d49
  • Swiss: 69b1fbe9fb4ea49e084fe6f9f9623d871bd22ceb5efad47b1a8d3708e6674868cad8bf088ced3976c2194360c7d58219
{
  "Version": "2012-10-17",
  "Id": "key-consolepolicy-4",
  "Statement": [
    {
      "Sid": "Enable enclave data processing for specific role",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::{ACCOUNT-ID}:role/{ROLE-NAME}"
      },
      "Action": [
        "kms:Decrypt",
        "kms:Encrypt",
        "kms:GenerateDataKey",
        "kms:GenerateDataKeyPair",
        "kms:GenerateDataKeyWithoutPlaintext",
        "kms:GenerateDataKeyPairWithoutPlaintext",
        "kms:GenerateRandom",
        "kms:GetKeyPolicy"
      ],
      "Resource": "*",
      "Condition": {
        "StringEqualsIgnoreCase": {
          "kms:RecipientAttestation:PCR8": "{PCR8-VALUE}"
        }
      }
    },
    {
      "Sid": "Allow GetKeyPolicy to co-signer",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::{ACCOUNT-ID}:role/{ROLE-NAME}"
      },
      "Action": "kms:GetKeyPolicy",
      "Resource": "*"
    },
    {
      "Sid": "Allow policy management to root user",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::{ACCOUNT-ID}:root"
      },
      "Action": [
        "kms:DescribeKey",
        "kms:GetKeyPolicy",
        "kms:PutKeyPolicy",
        "kms:CreateAlias"
      ],
      "Resource": "*"
    }
  ]
}

Aviso possivel no KMS

Ao colar a policy, a AWS pode mostrar:

Unsupported Action For Condition Key

Nessa configuracao, esse aviso pode ser ignorado. A condicao kms:RecipientAttestation:PCR8 so e avaliada nas chamadas que carregam atestado do enclave.

O que copiar ao final deste passo

Copie o KMS ARN.

Formato:

arn:aws:kms:{KEY-REGION}:{ACCOUNT-ID}:key/{KEY-ID}

Exemplo:

arn:aws:kms:us-east-1:123456789012:key/abcd1234-abcd-1234-abcd-1234567890ab

Resultado esperado

Ao final desse passo, a chave KMS existe e a key policy foi salva.

Passo 4: completar as permissoes da IAM Role

Agora volte ao IAM e complete as permissoes da role criada no passo 1.

Anexar policy gerenciada

  1. abra a role criada;
  2. na secao Permissions policies, clique em Attach policies;
  3. selecione AmazonSSMManagedInstanceCore;
  4. clique em Add permissions.

Criar inline policy

Depois:

  1. ainda na secao Permissions policies, clique em Create inline policy;
  2. escolha a aba JSON;
  3. cole a policy abaixo;
  4. salve com um nome claro.

Troque:

  • {BUCKET-NAME} pelo nome real do bucket;
  • {KEY-REGION} pela regiao da KMS;
  • {ACCOUNT-ID} pelo ID da conta;
  • {KEY-ID} pelo ID real da chave.
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ListBuckets",
      "Effect": "Allow",
      "Action": "s3:ListAllMyBuckets",
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "s3:ListBucket",
        "s3:GetBucketLocation"
      ],
      "Resource": "arn:aws:s3:::{BUCKET-NAME}"
    },
    {
      "Sid": "WritePermissionsOnBucket",
      "Effect": "Allow",
      "Action": [
        "s3:PutObject",
        "s3:PutObjectAcl",
        "s3:GetObject",
        "s3:GetObjectAcl",
        "s3:DeleteObject"
      ],
      "Resource": "arn:aws:s3:::{BUCKET-NAME}/*"
    },
    {
      "Sid": "AccessToTheKey",
      "Effect": "Allow",
      "Action": [
        "kms:Encrypt",
        "kms:Decrypt",
        "kms:GenerateDataKey",
        "kms:GenerateDataKeyPair",
        "kms:GenerateDataKeyWithoutPlaintext",
        "kms:GenerateDataKeyPairWithoutPlaintext",
        "kms:GenerateRandom",
        "kms:GetKeyPolicy"
      ],
      "Resource": [
        "arn:aws:kms:{KEY-REGION}:{ACCOUNT-ID}:key/{KEY-ID}"
      ]
    }
  ]
}

Resultado esperado

Ao final desse passo, a IAM Role tem:

  • AmazonSSMManagedInstanceCore;
  • a inline policy com acesso ao bucket e a chave KMS.

Passo 5: criar a instancia EC2

Requisito de tipo de instancia

Use apenas:

  • c5.xlarge
  • c5a.xlarge

Motivo:

  • o enclave precisa de no minimo 2 vCPUs dedicadas e 4 GB de memoria;
  • o Nitro Enclaves pode usar ate 50% dos recursos da instancia host;
  • o minimo recomendado aqui e 4 vCPUs e 8 GB de RAM.

Criar a instancia

No console da AWS:

  1. abra EC2;
  2. clique em Launch instances;
  3. informe o nome da instancia;
  4. escolha a AMI Amazon Linux 2023 AMI com arquitetura 64-bit (x86);
  5. em Instance type, escolha c5.xlarge;
  6. se c5.xlarge nao estiver disponivel na regiao, use c5a.xlarge;
  7. em Network settings, restrinja o acesso SSH ao minimo necessario;
  8. em Advanced details, configure:
    • IAM instance profile: a role criada anteriormente;
    • Nitro Enclave: Enable;
    • Metadata version: V2 only (token required);
    • Metadata response hop limit: no minimo 2;
  9. revise a configuracao;
  10. clique em Launch instance.

Exemplo:

  • Name: hotwallets-cosigner-1-ec2
  • AMI: Amazon Linux 2023 AMI
  • Architecture: 64-bit (x86)
  • Instance type: c5.xlarge
  • IAM instance profile: hotwallets-cosigner-1-role
  • Nitro Enclave: Enabled
  • IMDS: V2 only
  • Hop limit: 2

Resultado esperado

Ao final desse passo, a EC2 esta criada, usa a IAM Role correta e tem Nitro Enclaves habilitado.

Recomendacoes adicionais de seguranca

E recomendado revisar:

  • restricao de SSH ao menor conjunto de IPs possivel;
  • VPC e subnet para evitar exposicao desnecessaria;
  • security groups bem restritos;
  • separacao de bucket, chave e role entre cosigners diferentes.

Repetir para o segundo cosigner

Como a Hotwallets exige no minimo 2 cosigners, repita o processo para o segundo cosigner:

  1. crie a segunda IAM Role;
  2. crie o segundo bucket S3;
  3. crie a segunda KMS key;
  4. complete as permissoes da segunda role;
  5. crie a segunda EC2 com Nitro Enclaves.

Checklist final antes do instalador

Antes de executar install-ec2.sh, confirme para cada cosigner:

  • existe uma IAM Role dedicada;
  • existe um bucket S3 dedicado;
  • existe uma KMS key dedicada;
  • a role tem AmazonSSMManagedInstanceCore;
  • a role tem a inline policy correta;
  • a EC2 usa Amazon Linux 2023 AMI;
  • a EC2 usa c5.xlarge ou c5a.xlarge;
  • a EC2 esta com Nitro Enclave habilitado;
  • a EC2 esta com Metadata version em V2 only;
  • a EC2 esta com Metadata response hop limit em 2 ou mais.

Se qualquer item estiver pendente, finalize a preparacao antes de seguir para a instalacao do cosigner.