1 | const ini = require('ini')
|
2 | const chalk = require('chalk')
|
3 | const fs = require('fs-extra')
|
4 | const fsOpts = { encoding: 'utf8' }
|
5 | const verifyAccess = require('../login/verify-aws-access')
|
6 | const { indent, bulletize } = require('./indent-bullet')
|
7 | const indent2 = indent.bind(null, 2)
|
8 |
|
9 | const lsCred = 'ls -l ~/.aws/credentials'
|
10 | const catCred = 'cat ~/.aws/credentials'
|
11 | const chmodCred = 'chmod 644 ~/.aws/credentials'
|
12 | const chownCred = 'sudo chown `whoami` ~/.aws/credentials'
|
13 |
|
14 | const credFormat = `[default]
|
15 | aws_access_key_id = ALPHANUMERIC20CHARS1
|
16 | aws_secret_access_key = ALPHANUMERICand+and/and40charactersEXACT`
|
17 | const logCred = `Log the contents of your credentials file with the following command:
|
18 | ${chalk.italic.gray(catCred)}`
|
19 | const awsFail = 'Connection to AWS S3 failed'
|
20 | const badCreds = `Check the internet connection and then confirm the
|
21 | AWS access ID and secret in ~/.aws/credentials are correct.`
|
22 | const newCreds = chalk`To enter new credentials, run {italic.gray blink login}`
|
23 | const noCredFile = `The credentials file was not found
|
24 | The AWS Access Key Id and AWS Secret Access Key should be
|
25 | included in a file named "credentials" located at ~/.aws/`
|
26 | const writePermissions = 'No write permissions for the AWS credentials file located at ~/.aws/'
|
27 | const readPermissions = 'No read permissions for the AWS credentials file located at ~/.aws/'
|
28 | const logCredPerm = `Check permission with the following command:
|
29 | ${chalk.italic.gray(lsCred)}`
|
30 | const fixPermissions = `If the user shows as 'root' and/or not your username, try the following:
|
31 | ${chalk.italic.gray(chownCred)}
|
32 | If the file permissions do not match "-rw-r--r--", try the following:
|
33 | ${chalk.italic.gray(chmodCred)}`
|
34 | const credAccess = 'There is a problem accessing the AWS credentials file located at ~/.aws/'
|
35 | const credParse = `Could not parse the AWS credentials file located at ~/.aws/
|
36 | Check the formatting of the file contents`
|
37 | const credDefault = `The AWS credentials file is missing the default profile
|
38 | Add the default profile to the credentials file located at ~/.aws/
|
39 | or run "blink login" and provide a valid AWS access ID and secret`
|
40 | const noAwsId = `There is no key "aws_access_key_id" for the default profile or it is
|
41 | not assigned a value in the credentials file located at ~/.aws/`
|
42 | const awsIdLength = 'The aws_access_key_id must be exactly 20 characters long, yours is'
|
43 | const awsIdChars = 'The aws_access_key_id must only contain alphanumeric characters'
|
44 | const noAwsSecret = `There is no key "aws_secret_access_key" for the default profile or it is
|
45 | not assigned a value in the credentials file located at ~/.aws/`
|
46 | const awsSecretLength = 'The aws_secret_access_key must be exactly 40 characters long, yours is'
|
47 | const awsSecretChars = 'The aws_secret_access_key must only contain numbers, letters, +, and /'
|
48 | const loginFix = chalk`Run {italic.gray blink login} and provide a valid AWS access ID and secret`
|
49 | const permFormat = `Output should resemble the following:
|
50 | [permissions] [links] [user] ...`
|
51 |
|
52 | module.exports = async ({ env }) => {
|
53 | const warnings = []
|
54 | const credPath = `${env.home}/.aws/credentials`
|
55 |
|
56 | try {
|
57 | await fs.access(credPath, fs.constants.W_OK)
|
58 | } catch (err) {
|
59 | if (err.code === 'EACCES') warnings.push(`${writePermissions}\n${indent2(`${logCredPerm}\n${permFormat}\n${fixPermissions}`)}`)
|
60 | }
|
61 |
|
62 | try {
|
63 | await verifyAccess()
|
64 | } catch (err) {
|
65 | let bullets = []
|
66 |
|
67 | try {
|
68 | const data = await fs.readFile(credPath, fsOpts)
|
69 |
|
70 | try {
|
71 | const config = ini.parse(data)
|
72 |
|
73 | if (!config.default || typeof config.default !== 'object') {
|
74 | bullets.push(`${credDefault}\nExample file contents:\n${indent2(credFormat)}\n${logCred}`)
|
75 | } else {
|
76 | const contentErrors = []
|
77 | const creds = config.default
|
78 |
|
79 | if (!creds.aws_access_key_id || typeof creds.aws_access_key_id !== 'string') {
|
80 | contentErrors.push(`${noAwsId}\n${loginFix}\n${logCred}`)
|
81 | } else {
|
82 | if (creds.aws_access_key_id.length !== 20) {
|
83 | contentErrors.push(`${awsIdLength} ${creds.aws_access_key_id.length}\n${loginFix}\n${logCred}`)
|
84 | }
|
85 | if (/[^\w]/.test(creds.aws_access_key_id)) {
|
86 | contentErrors.push(`${awsIdChars}\n${loginFix}\n${logCred}`)
|
87 | }
|
88 | }
|
89 |
|
90 | if (!creds.aws_secret_access_key || typeof creds.aws_secret_access_key !== 'string') {
|
91 | contentErrors.push(`${noAwsSecret}\n${loginFix}\n${logCred}`)
|
92 | } else {
|
93 | if (creds.aws_secret_access_key.length !== 40) {
|
94 | contentErrors.push(`${awsSecretLength} ${creds.aws_secret_access_key.length}\n${loginFix}\n${logCred}`)
|
95 | }
|
96 | if (/[^\w/+]/.test(creds.aws_secret_access_key)) {
|
97 | contentErrors.push(`${awsSecretChars}\n${loginFix}\n${logCred}`)
|
98 | }
|
99 | }
|
100 | if (contentErrors.length) {
|
101 | bullets = bullets.concat(contentErrors)
|
102 | } else {
|
103 |
|
104 | bullets.push(`${badCreds}\n${logCred}\n${newCreds}`)
|
105 | }
|
106 | }
|
107 | } catch (err) {
|
108 | bullets.push(`${credParse}\nExample file contents:\n${indent2(credFormat)}`)
|
109 | }
|
110 | } catch (err) {
|
111 | if (err.code === 'ENOENT') bullets.push(`${noCredFile}\nExample file contents:\n${indent2(credFormat)}\n${loginFix}`)
|
112 | else if (err.code === 'EACCES') bullets.push(`${readPermissions}\n${logCredPerm}\n${permFormat}\n${fixPermissions}`)
|
113 | else bullets.push(`${credAccess}\n${logCredPerm}\n${permFormat}\n${fixPermissions}`)
|
114 | }
|
115 | warnings.push(`${awsFail}\n${indent2(bullets.map(bulletize).join('\n'))}`)
|
116 | }
|
117 | return { warnings, details: [] }
|
118 | }
|