Provision creates a new IAM user in the account specified by s, and configures a bucket according to the values in s. The credentials in s must have the IAMFullAccess and AmazonS3FullAccess permissions in order to succeed. The name of the created IAM user is "checkup-monitor-s3-public". It will hav
()
| 143 | // Provision need only be called once per status page (bucket), |
| 144 | // not once per endpoint. |
| 145 | func (s Storage) Provision() (types.ProvisionInfo, error) { |
| 146 | const iamUser = "checkup-monitor-s3-public" |
| 147 | var info types.ProvisionInfo |
| 148 | |
| 149 | // default region (required, but regions don't apply to S3, kinda weird) |
| 150 | if s.Region == "" { |
| 151 | s.Region = "us-east-1" |
| 152 | } |
| 153 | |
| 154 | svcIam := iam.New(session.New(), &aws.Config{ |
| 155 | Credentials: credentials.NewStaticCredentials(s.AccessKeyID, s.SecretAccessKey, ""), |
| 156 | Region: &s.Region, |
| 157 | }) |
| 158 | |
| 159 | // Create a new user, just for reading the check files |
| 160 | resp, err := svcIam.CreateUser(&iam.CreateUserInput{ |
| 161 | UserName: aws.String(iamUser), |
| 162 | }) |
| 163 | if err != nil { |
| 164 | return info, fmt.Errorf("Error creating user: %s\n\nTry deleting the user in the AWS control panel and try again.", err) |
| 165 | } |
| 166 | info.Username = *resp.User.UserName |
| 167 | info.UserID = *resp.User.UserId |
| 168 | |
| 169 | // Restrict the user to only reading S3 buckets |
| 170 | _, err = svcIam.AttachUserPolicy(&iam.AttachUserPolicyInput{ |
| 171 | PolicyArn: aws.String("arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess"), |
| 172 | UserName: aws.String(iamUser), |
| 173 | }) |
| 174 | if err != nil { |
| 175 | return info, err |
| 176 | } |
| 177 | |
| 178 | // Give the user a key (this will become public as it is read-only) |
| 179 | resp3, err := svcIam.CreateAccessKey(&iam.CreateAccessKeyInput{ |
| 180 | UserName: aws.String(iamUser), |
| 181 | }) |
| 182 | if err != nil { |
| 183 | return info, err |
| 184 | } |
| 185 | info.PublicAccessKeyID = *resp3.AccessKey.AccessKeyId |
| 186 | info.PublicAccessKey = *resp3.AccessKey.SecretAccessKey |
| 187 | |
| 188 | // Prepare to talk to S3 |
| 189 | svcS3 := s3.New(session.New(), &aws.Config{ |
| 190 | Credentials: credentials.NewStaticCredentials(s.AccessKeyID, s.SecretAccessKey, ""), |
| 191 | Region: &s.Region, |
| 192 | }) |
| 193 | |
| 194 | // Create a bucket to hold all the checks |
| 195 | _, err = svcS3.CreateBucket(&s3.CreateBucketInput{ |
| 196 | Bucket: &s.Bucket, |
| 197 | }) |
| 198 | if err != nil { |
| 199 | return info, err |
| 200 | } |
| 201 | |
| 202 | // Configure its CORS policy to allow reading from status pages |