1"use strict";(self.webpackChunkopa_website=self.webpackChunkopa_website||[]).push([[26030],{28453:(e,n,i)=>{i.d(n,{R:()=>r,x:()=>a});var s=i(96540);const t={},o=s.createContext(t);function r(e){const n=s.useContext(o);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:r(e.components),s.createElement(o.Provider,{value:n},e.children)}},95013:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>l,contentTitle:()=>c,default:()=>u,frontMatter:()=>a,metadata:()=>s,toc:()=>d});const s=JSON.parse('{"id":"deploy/aws/ecs","title":"Deploying OPA on AWS ECS","description":"Amazon ECS (Elastic Container Service) is a managed platform for running","source":"@site/docs/deploy/aws/ecs.mdx","sourceDirName":"deploy/aws","slug":"/deploy/aws/ecs","permalink":"/docs/deploy/aws/ecs","draft":false,"unlisted":false,"tags":[],"version":"current","sidebarPosition":3,"frontMatter":{"sidebar_label":"ECS","sidebar_position":3,"title":"Deploying OPA on AWS ECS"},"sidebar":"docsSidebar","previous":{"title":"EKS","permalink":"/docs/deploy/aws/eks"},"next":{"title":"Google Cloud","permalink":"/docs/deploy/google-cloud/"}}');var t=i(74848),o=i(28453),r=i(51107);const a={sidebar_label:"ECS",sidebar_position:3,title:"Deploying OPA on AWS ECS"},c=void 0,l={},d=[{value:"Supplying Configuration to OPA",id:"supplying-configuration-to-opa",level:2},{value:"Selecting or Creating an ECS Cluster",id:"selecting-or-creating-an-ecs-cluster",level:2},{value:"Accessing the OPA service",id:"accessing-the-opa-service",level:2}];function h(e){const n={a:"a",admonition:"admonition",code:"code",h2:"h2",li:"li",mermaid:"mermaid",ol:"ol",p:"p",strong:"strong",ul:"ul",...(0,o.R)(),...e.components},{InlineEditable:i,ParamCodeBlock:s,ParamProvider:a}=n;return i||p("InlineEditable",!0),s||p("ParamCodeBlock",!0),a||p("ParamProvider",!0),(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.p,{children:"Amazon ECS (Elastic Container Service) is a managed platform for running\ncontainerized applications. Software already packaged as containers, like OPA,\nis easy to run on ECS. ECS takes care of scaling, networking, and\ninfrastructure, allowing you to focus on building and integrating your\napplications."}),"\n",(0,t.jsxs)(n.p,{children:["ECS is great for hosting a centralized OPA, Policy Decision Point (PDP) service\nto be accessed by Policy Enforcement Points (PEPs, e.g. business apps and\nservices) running elsewhere in your environment. ECS also supports running OPA\nas a\n",(0,t.jsx)(n.a,{href:"https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs_services.html?icmpid=docs_ecs_hp-deploy-serviceType#service_scheduler_daemon",children:"daemon"}),"\nor additional container alongside your other application containers too but this\npattern is not covered here."]}),"\n",(0,t.jsx)(n.p,{children:"This guide will explain the steps and key considerations for deploying an OPA\nservice using ECS."}),"\n",(0,t.jsx)(n.h2,{id:"supplying-configuration-to-opa",children:"Supplying Configuration to OPA"}),"\n",(0,t.jsx)(n.p,{children:"While the default OPA configuration is simple, OPA has many different options\nand settings. Like many other tools, OPA is commonly configured using a file\nmounted into its container at a known path. There are many ways to configure OPA\non ECS:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Loading a config file from S3 and using\n",(0,t.jsx)(n.a,{href:"../../configuration/#using-environment-variables-in-configuration",children:"environment variable substitution"})," for secret values from KMS."]}),"\n",(0,t.jsxs)(n.li,{children:["Using ",(0,t.jsx)(n.a,{href:"https://docs.aws.amazon.com/appconfig/latest/userguide/what-is-appconfig.html",children:"AWS AppConfig"}),"\nand the ",(0,t.jsx)(n.code,{children:"aws-appconfig-agent"})," sidecar container to load the config file at\nstart up."]}),"\n",(0,t.jsxs)(n.li,{children:["Using ",(0,t.jsx)(n.a,{href:"../../configuration/#setting-configuration-via-cli-arguments",children:"command line flags"}),"\nto set values and not using a config file at all."]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"Since the preferred option is largely dependent on your organization's approach\nto secrets management, we leave this exercise to the reader. The following guide\nuses command line configuration with secrets loaded from KMS, to keep the\nexample simple to follow."}),"\n",(0,t.jsx)(n.h2,{id:"selecting-or-creating-an-ecs-cluster",children:"Selecting or Creating an ECS Cluster"}),"\n",(0,t.jsx)(n.p,{children:"An ECS cluster is a logical grouping of Amazon Elastic Container Service (ECS)\nresources used to run and manage Docker
1containers using AWS Fargate."}),"\n",(0,t.jsxs)(n.p,{children:["All applications running in ECS are part of an ECS cluster. When creating a\ncluster for OPA, it's recommended to use the Fargate infrastructure type -\nrather than EC2. Please see our ",(0,t.jsx)(n.a,{href:"../aws/ec2",children:"EC2 Guide"})," if you'd like\nto run OPA on EC2."]}),"\n",(0,t.jsx)(n.p,{children:"Within our cluster, we will be running OPA using the following architecture:"}),"\n",(0,t.jsx)(n.mermaid,{value:'graph\n subgraph AWS\n subgraph KMS\n Secret\n end\n subgraph ECS Cluster\n subgraph Service\n subgraph Task\n opa["OPA Container"] <--\x3e Secret\n end\n end\n end\n end'}),"\n",(0,t.jsxs)(a,{initialParams:{service:"my-opa",region:"us-east-1",secretARN:"arn:aws:secretsmanager...",taskRoleArn:"arn:aws:iam:...",version:"..."},children:[(0,t.jsx)(r.A,{as:"h2",id:"creating-a-secret-and-iam-role-for-your-opa-task",children:"Creating a Secret and IAM Role for your OPA Task"}),(0,t.jsx)(n.p,{children:"OPA needs to download policy at startup. Often credentials are needed to\ndownload new policy and data bundles. These might be an API token, or\nusername/password combination depending on how your bundles are hosted.\nThese credentials must be securely stored. In this section, we\u2019ll create a\nsecret in AWS Secrets Manager, an IAM policy to access the secret, and an IAM\nrole with that policy for the ECS task to use."}),(0,t.jsxs)(n.admonition,{type:"tip",children:[(0,t.jsxs)(n.p,{children:["Unsure how to authenticate OPA such that it can download bundles? Have a look at\nthe ",(0,t.jsx)(n.a,{href:"../../configuration",children:"configuration"})," documentation."]}),(0,t.jsxs)(n.p,{children:["In this example we set an example ",(0,t.jsx)(n.code,{children:"TOKEN"})," from the secret as an example using\n",(0,t.jsx)(n.a,{href:"../../configuration#setting-configuration-via-cli-arguments",children:"CLI flags"}),"."]})]}),(0,t.jsxs)(n.p,{children:["Create a secret with any variables you need such as ",(0,t.jsx)(n.code,{children:"TOKEN"})," etc. Once you have\ncreated the secret, note it's ARN here set it in the later\nsteps: ",(0,t.jsx)(i,{paramKey:"secretARN"}),".\nCreate a IAM policy with the following rules to allow the OPA task to\naccess the secret:"]}),(0,t.jsx)(s,{children:'\n{\n "Version": "2012-10-17",\n "Statement": [\n {\n "Effect": "Allow",\n "Action": "secretsmanager:GetSecretValue",\n "Resource": "{{secretARN}}\n }\n ]\n}\n'}),(0,t.jsxs)(n.p,{children:["Now you can create a new Role referencing this policy to use as the\n",(0,t.jsx)(n.code,{children:"taskRoleArn"})," for the rest of the guide. When you have created the role, note\nthe task's ARN here to populate the later steps:\n",(0,t.jsx)(i,{paramKey:"taskRoleArn"}),"."]}),(0,t.jsx)(r.A,{as:"h2",id:"creating-an-opa-task-definition",children:"Creating an OPA Task Definition"}),(0,t.jsx)(n.p,{children:"An ECS task definition is a blueprint that describes how containers\nshould run in AWS ECS, specifying details like container images, commands and\nresource requirements. In this section, we will build a task definition for use\non ECS to run OPA."}),(0,t.jsx)(n.p,{children:"Before continuing, please ensure you have set the following:"}),(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Service Name: ",(0,t.jsx)(i,{paramKey:"service"})," (This is the name for the\nservice as it will appear in ECS)"]}),"\n",(0,t.jsxs)(n.li,{children:["Secret ARN: ",(0,t.jsx)(i,{paramKey:"secretARN"})," (if configuration depends\non secret values for some variables)"]}),"\n",(0,t.jsxs)(n.li,{children:["Region: ",(0,t.jsx)(i,{paramKey:"region"})]}),"\n",(0,t.jsxs)(n.li,{children:["OPA Version: ",(0,t.jsx)(i,{paramKey:"version"}),", e.g. ",(0,t.jsx)(n.code,{children:"X.Y.Z"})," not ",(0,t.jsx)(n.code,{children:"latest"}),"\nor ",(0,t.jsx)(n.code,{children:"vX.Y.Z"}),". Review the\n",(0,t.jsx)(n.a,{href:"https://hub.docker.com/r/openpolicyagent/opa/tags",children:"OPA images"})," for a list of\navailable versions."]}),"\n"]}),(0,t.jsx)(s,{children:'\n{\n "family": "{{service}}",\n "containerDefinitions": [\n {\n "name": "opa",\n "image": "openpolicyagent/opa:{{version}}",\n "cpu": 0,\n "portMappings": [\n {\n "name": "opa-8181-tcp",\n "containerPort": 8181,\n "hostPort": 8181,\n "protocol": "tcp"\n }\n ],\n "essential": true,\n "command": [\n "--server",\n "--set",\n ""default_decision=/http/example/authz/allow"",\n "--set",\n ""services.example_com.url=https://example.com/control-plane-api/v1"",\n "--set",\n ""services.example_com.credentials.bearer.token=${TOKEN}"",\n ],\n "healthCheck": {\n "command": [\n "CMD",\n "/opa",\n "eval",\n "-f", "pretty",\n "--fail",\n "200 = http.send({"url": "http://localhost:8181/health", "method": "get"}).status_code"\n ],\n "interval": 30,\n "timeout": 5,\n "retries": 2,\n "startPeriod": 10\n },\n "environment": [],\n "mountPoints": [],\n "volumesFrom": [],\n "secrets": [\n {\n "name": "TOKEN",\n "valueFrom": "{{secretARN}}:TOKEN::"\n },\n ],\n "logConfiguration": {\n "logDriver": "awslogs",\n "options": {\n "awslogs-group": "/ecs/{{service}}",\n "mode": "non-blocking",\n "awslogs-create-group": "true",\n "max-buffer-size": "25m",\n "awslogs-region": "{{region}}",\n "awslogs-stream-prefix": "ecs"\n }\n },\n "systemControls": []\n }\n ],\n "taskRoleArn": "{{taskRoleArn}}",\n "networkMode": "awsvpc",\n "volumes": [],\n "placementConstraints": [],\n "requiresCompatibilities": [\n "FARGATE"\n ],\n "cpu": "1024",\n "memory": "2048",\n "runtimePlatform": {\n "cpuArchitecture": "X86_64",\n "operatingSystemFamily": "LINUX"\n }\n}\n'}),(0,t.jsx)(n.admonition,{type:"warning",children:(0,t.jsxs)(n.p,{children:["If you have configured OPA to use another port than ",(0,t.jsx)(n.code,{children:"8181"}),", make sure to update\nthe health ",(0,t.jsx)(n.code,{children:"localhost"})," port too."]})}),(0,t.jsx)(r.A,{as:"h2",id:"deploying-opa-on-the-cluster",children:"Deploying OPA on the Cluster"}),(0,t.jsx)(n.p,{children:"Once you have a task definition in place, you can deploy it to your ECS cluster."}),(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsx)(n.li,{children:"Create a new service in the cluster where you'd like to deploy OPA."}),"\n",(0,t.jsxs)(n.li,{children:["Use a ",(0,t.jsx)(n.code,{children:"Service"})," as the ",(0,t.jsx)(n.code,{children:"Application type"}),", OPA will be a long running\nservice."]}),"\n",(0,t.jsxs)(n.li,{children:["Select ",(0,t.jsx)(i,{paramKey:"service"})," as the ",(0,t.jsx)(n.code,{children:"Family"})," of task\ndefinitions."]}),"\n"]}),(0,t.jsx)(n.p,{children:"Once the service is created, ECS will start a task using the task definition\nand you should see the OPA is accessible shortly after."})]}),"\n",(0,t.jsx)(n.h2,{id:"accessing-the-opa-service",children:"Accessing the OPA service"}),"\n",(0,t.jsx)(n.p,{children:"There are many options to access the OPA service running on ECS from your PEPs.\nThe right option for your use case will depend on the location of OPA's callers\nin your infrastru
1cture - among other factors like security and performance. A\nbrief overview of some options is provided below."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Application Load Balancer (ALB)"}),": Well suited to OPA's REST API HTTP\ntraffic, ALB operates at Layer 7 and supports advanced routing features. Use\nan ALB when you need to route requests to OPA based on URL paths or host\nheaders or require integration with AWS services like AWS WAF."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Network Load Balancer (NLB)"}),": Best suited for high performance OPA use\ncases where response times are critical. Read more about\n",(0,t.jsx)(n.a,{href:"https://docs.aws.amazon.com/AmazonECS/latest/developerguide/nlb.html",children:"NLB integration with ECS"}),"."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Service Discovery with AWS Cloud Map"}),": Allows internal clients within the\nsame VPC to access the OPA service using DNS names. Opt for this when your OPA\nclients are inside your AWS network, and you want to avoid exposing services\nto the internet."]}),"\n"]})]})}function u(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(h,{...e})}):h(e)}function p(e,n){throw new Error("Expected "+(n?"component":"object")+" `"+e+"` to be defined: you likely forgot to import, pass, or provide it.")}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.