aws-solutions / smart-product-solution

The Smart Product Solution is a customer deployable reference architecture to help manufacturers to jumpstart development of innovative connected/smart product services.
Apache License 2.0
28 stars 20 forks source link

Error deploying CICDCustomResource, AccessDenied: Access Denied #20

Closed iotFab closed 4 years ago

iotFab commented 4 years ago

Solution Cloudformation deployment give the following error : CICDCustomResource

Failed to create resource. See the details in CloudWatch Log Stream: 2020/07/29/[$LATEST]cfe1b0bcd6df42bf82ef3b195399f041

Inside that log stream I found the following logs :

{
    "errorType": "Error",
    "errorMessage": "AccessDenied: Access Denied",
    "stack": [
        "Error: AccessDenied: Access Denied",
        "    at Runtime.exports.handler (/var/task/index.js:134:15)",
        "    at processTicksAndRejections (internal/process/task_queues.js:97:5)"
    ]
}

The code block responsible for this error is :

if (event.ResourceType === 'Custom::CreateCommit') {
    /**
     * Create commit when the solution is created
     */
    if (event.RequestType === 'Create') {
      try {
        Logger.log(
          Logger.levels.ROBUST,
          `${event.LogicalResourceId}:${event.RequestType}`
        );

        const _repo = process.env.CODECOMMIT_REPO
        const s3Bucket = process.env.CODE_BUCKET;
        const s3Key = process.env.CODE_KEY;
        const codeSource = process.env.CODE_SOURCE;
        const s3params = {
          Bucket: s3Bucket,
          Key: `${s3Key}/${codeSource}`
        };

        const file = fs.createWriteStream('/tmp/smart-product-solution.zip');
        let smartProductData = await s3.getObject(s3params).promise();
        file.write(smartProductData.Body, () => {
          file.end();
        });

        execSync('rm -rf /tmp/smart-product && mkdir /tmp/smart-product');
        let zip = new admZip(`/tmp/${codeSource}`);
        zip.extractAllTo('/tmp/smart-product', true);
        const data = await walk('/tmp/smart-product')
        let i, j, temparray, chunk = 99;
        let parentCommitId = ''
        let codeCommitParams = {}
        for (i = 0, j = data.length; i < j; i += chunk) {
          temparray = data.slice(i, i + chunk);
          const filesList = []
          for (let k = 0; k < temparray.length; k++) {
            const fileDetails = {
              filePath: temparray[k].split('smart-product/')[1],
              fileContent: Buffer.from(fs.readFileSync(temparray[k]))
            }
            filesList.push(fileDetails)
          }
          if (!parentCommitId) {
            codeCommitParams = {
              branchName: 'master', /* required */
              repositoryName: _repo, /* required */
              putFiles: filesList,
              authorName: 'smart-product-pipeline',
              commitMessage: 'initial commit for smart product'
            }
          }
          else if (parentCommitId) {
            codeCommitParams = {
              branchName: 'master', /* required */
              repositoryName: _repo, /* required */
              parentCommitId: parentCommitId,
              putFiles: filesList,
              authorName: 'smart-product-pipeline',
              commitMessage: 'initial commit for smart product, adding more code artifacts'
            }
          }

          Logger.log(
            Logger.levels.ROBUST,
            `params: ${JSON.stringify(codeCommitParams)}`
          );
          const resp = await codecommit.createCommit(codeCommitParams).promise()
          parentCommitId = resp.commitId
        }

        const _responseData = {
          Method: `${event.LogicalResourceId}:${event.RequestType} `
        };

        await sendResponse(
          event,
          context.logStreamName,
          'SUCCESS',
          _responseData
        );
      } catch (err) {
        const _responseData = {
          Error: err,
        };
        await sendResponse(
          event,
          context.logStreamName,
          'FAILED',
          _responseData
        );
        throw new Error(err)
      }
    }

How to investigate this further ? Thank you, Fabian

iotFab commented 4 years ago

The problem is in line 64 of /source/resources/cicd/index.js

const _repo = process.env.CODECOMMIT_REPO
const s3Bucket = process.env.CODE_BUCKET;
const s3Key = process.env.CODE_KEY;
const codeSource = process.env.CODE_SOURCE;
const s3params = {
    Bucket: s3Bucket,
    Key: `${s3Key}/${codeSource}`
};
const file = fs.createWriteStream('/tmp/smart-product-solution.zip');
let smartProductData = await s3.getObject(s3params).promise();

according to the environment variable, this process is looking for a file inside our s3 bucket. We don't have the access because this particular file is not present.

Could you tell us what should be in that file and from where it comes ?

halfn0rmal commented 2 years ago

@iotFab Did you find a fix for this? I have the same issue

iotFab commented 2 years ago

@halfn0rmal I retry part of it and did not see the error anymore

halfn0rmal commented 2 years ago

@iotFab Thanks for you reply. I can see smart-product-solution.zip does not exist on my s3 bucket. Was the issue that the lambda that fails did not have permission to create this file? Or that the build did not create smart-product-solution.zip so the lambda can not access it? I will try your suggestions.

halfn0rmal commented 2 years ago

Can this issue be reopened? I have my s3 buckets public but the issue is still there. I have no smart-product-solution.zip. I can't see where this gets created during the build?