udondan / cdk-ssm-document Goto Github PK
View Code? Open in Web Editor NEWAWS CDK L3 construct for managing SSM Documents - DEPRECATED
License: Apache License 2.0
AWS CDK L3 construct for managing SSM Documents - DEPRECATED
License: Apache License 2.0
In ensureLambda()
you're creating a function whose name is constructed from the stack name and the resource type. If this name exceeds 64 characters, CDK throws an error.
Example:
export class StackWithAReallyRidiculouslyLongName extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
# ...
new Document(this, 'Document', {
# ...
})
}
}
The function created in ensureLambda() will construct a function name of StackWithAReallyRidiculouslyLongName-CFN-Resource-Custom-SSM-Document
, which is longer than 64 characters.
Cannot set an assume role on an Automation document to allow it to run as another role. See syntax here https://docs.aws.amazon.com/systems-manager/latest/userguide/document-schemas-features.html#automation-doc-syntax-examples
While instantiating a stack for the first time, my SSM document had an error in it that wasn't identified during the pre-deploy checks. During rollback, the Lambda function tried to delete the (non-existent) document anyway, and failed.
The error message below suggests that the IAM policy forbade it -- most likely due to the Condition
key in the policy -- but even if the Condition
key wasn't there, the DeleteDocument call probably would have failed anyway because the document failed to create in the first place.
Received response status [FAILED] from custom resource. Message returned: User: arn:aws:sts::xxxxxxxxx:assumed-role/xxxxxxxxxxxStack-CFN-Resource-Custom-SSM-Document/xxxxxxxxxxxxxxBuilderStack-CFN-Resource-Custom-SSM-Document is not authorized to perform: ssm:DeleteDocument on
resource: arn:aws:ssm:us-west-2:xxxxxxxxx:document/xxxxxxx because no identity-based policy allows the ssm:DeleteDocument action | Full error in CloudWatch 2022/03/24/[$LATEST]xxxxxxxxxxxxxx (RequestId:xxxxxxxxxxxx)
PS C:\Users\XXX\cdk-ssm> cdk ls
jsii.errors.JavaScriptError:
internal/modules/cjs/loader.js:638
throw err;
^
Error: Cannot find module 'js-yaml'
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:636:15)
at Function.Module._load (internal/modules/cjs/loader.js:562:25)
at Module.require (internal/modules/cjs/loader.js:692:17)
at require (internal/modules/cjs/helpers.js:25:18)
at Object. (C:\Users\XXX\AppData\Local\Temp\jsii-kernel-w7ZNRI\node_modules\cdk-ssm-document\lib\index.js:11:14)
at Module._compile (internal/modules/cjs/loader.js:778:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)
at Module.load (internal/modules/cjs/loader.js:653:32)
at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
at Module._load (internal/modules/cjs/loader.js:585:3)
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "C:\Users\XXX\cdk-ssm\app.py", line 6, in
from cdk_ssm.cdk_ssm_stack import CdkSsmStack
File "C:\Users\XXX\cdk-ssm\cdk_ssm\cdk_ssm_stack.py", line 5, in
from cdk_ssm_document import Document
File "C:\Users\XXX\AppData\Local\Programs\Python\Python39\lib\site-packages\cdk_ssm_document_init_.py", line 297, in
from .jsii import *
File "C:\Users\XXX\AppData\Local\Programs\Python\Python39\lib\site-packages\cdk_ssm_document_jsii_init.py", line 18, in
jsii_assembly = jsii.JSIIAssembly.load(
File "C:\Users\XXX\AppData\Local\Programs\Python\Python39\lib\site-packages\jsii_runtime.py", line 43, in load
kernel.load(assembly.name, assembly.version, os.fspath(assembly_path))
File "C:\Users\XXX\AppData\Local\Programs\Python\Python39\lib\site-packages\jsii_kernel_init.py", line 254, in load
self.provider.load(LoadRequest(name=name, version=version, tarball=tarball))
File "C:\Users\XXX\AppData\Local\Programs\Python\Python39\lib\site-packages\jsii_kernel\providers\process.py", line 338, in load
return self._process.send(request, LoadResponse)
File "C:\Users\XXX\AppData\Local\Programs\Python\Python39\lib\site-packages\jsii_kernel\providers\process.py", line 326, in send
raise JSIIError(resp.error) from JavaScriptError(resp.stack)
jsii.errors.JSIIError: Cannot find module 'js-yaml'
PS C:\Users\XXX\cdk-ssm> npm list -g
C:\Users\XXX\AppData\Roaming\npm
+-- [email protected]
| +-- @aws-cdk/[email protected]
| | +-- [email protected]
| | -- [email protected] deduped | +-- @aws-cdk/[email protected] | | +-- @aws-cdk/[email protected] | | |
-- [email protected]
| | | +-- [email protected]
| | | +-- [email protected]
| | | -- [email protected] | | +-- [email protected] deduped | | +-- [email protected] | | +-- [email protected] | | +-- [email protected] | | | +-- [email protected] | | | +-- [email protected] | | |
-- [email protected] deduped
| | -- [email protected] | | +-- [email protected] deduped | | +-- [email protected] deduped | | +-- [email protected] deduped | | +-- [email protected] deduped | | +-- [email protected] deduped | | +-- [email protected] deduped | | +-- [email protected] deduped | | +-- [email protected] deduped | |
-- [email protected] deduped
| +-- @aws-cdk/[email protected]
| | +-- @aws-cdk/[email protected] deduped
| | -- [email protected] deduped | +-- @aws-cdk/[email protected] | +-- [email protected] | | +-- [email protected] | | | +-- [email protected] deduped | | | +-- [email protected] deduped | | | +-- [email protected] | | | |
-- [email protected]
| | | | +-- [email protected] deduped
| | | | +-- [email protected] deduped
| | | | +-- [email protected] deduped
| | | | +-- [email protected] deduped
| | | | +-- [email protected] deduped
| | | | +-- [email protected] deduped
| | | | -- [email protected] deduped | | | +-- [email protected] | | | +-- [email protected] | | | +-- [email protected] deduped | | | +-- [email protected] | | | +-- [email protected] | | | +-- [email protected] | | |
-- [email protected]
| | | +-- [email protected]
| | | +-- [email protected] deduped
| | | +-- [email protected] deduped
| | | +-- [email protected]
| | | +-- [email protected]
| | | +-- [email protected]
| | | | -- [email protected] deduped | | |
-- [email protected] deduped
| | +-- [email protected]
| | +-- [email protected]
| | +-- [email protected]
| | | +-- [email protected] deduped
| | | +-- [email protected]
| | | | -- [email protected] | | |
-- [email protected]
| | +-- [email protected]
| | | -- [email protected] deduped | | +-- [email protected] | | | +-- [email protected] | | | | +-- [email protected] | | | | | +-- [email protected] deduped | | | | |
-- [email protected]
| | | | +-- [email protected] deduped
| | | | -- [email protected] deduped | | | +-- [email protected] | | | |
-- [email protected] deduped
| | | +-- [email protected]
| | | +-- [email protected] deduped
| | | -- [email protected] deduped | |
-- [email protected]
| | +-- [email protected] deduped
| | +-- [email protected]
| | | +-- [email protected] deduped
| | | +-- [email protected]
| | | | +-- [email protected]
| | | | | +-- [email protected]
| | | | | -- [email protected] | | | |
-- [email protected] deduped
| | | +-- [email protected] deduped
| | | -- [email protected] deduped | |
-- [email protected] deduped
| +-- [email protected]
| | +-- [email protected]
| | | +-- [email protected]
| | | +-- [email protected]
| | | -- [email protected] | | +-- [email protected] | | +-- [email protected] | | +-- [email protected] | | +-- [email protected] | | +-- [email protected] | | +-- [email protected] | | | +-- [email protected] | | |
-- [email protected] deduped
| | +-- [email protected]
| | -- [email protected] | | +-- [email protected] | |
-- [email protected]
| +-- [email protected]
| +-- [email protected]
| | +-- @aws-cdk/[email protected] deduped
| | +-- @aws-cdk/[email protected] deduped
| | +-- [email protected] deduped
| | +-- [email protected] deduped
| | +-- [email protected] deduped
| | -- [email protected] deduped | +-- [email protected] | +-- [email protected] | +-- [email protected] | | +-- [email protected] | | +-- [email protected] | | +-- [email protected] | | | +-- [email protected] deduped | | |
-- [email protected] deduped
| | -- [email protected] | +-- [email protected] | | +-- [email protected] | | +-- [email protected] | | | +-- [email protected] deduped | | |
-- [email protected]
| | +-- [email protected]
| | +-- [email protected] deduped
| | +-- [email protected]
| | | -- [email protected] deduped | |
-- [email protected]
| +-- [email protected]
| | +-- [email protected]
| | | -- [email protected] | | +-- [email protected] | | |
-- [email protected]
| | -- [email protected] | |
-- [email protected]
| +-- [email protected]
| | -- [email protected] | | +-- [email protected] | |
-- [email protected]
| +-- [email protected]
| | -- [email protected] | |
-- [email protected]
| +-- [email protected]
| | +-- [email protected]
| | | -- [email protected] deduped | | +-- [email protected] | | |
-- [email protected]
| | +-- [email protected]
| | | +-- @tootallnate/[email protected]
| | | +-- [email protected] deduped
| | | -- [email protected] deduped | | +-- [email protected] | | | +-- [email protected] deduped | | |
-- [email protected] deduped
| | +-- [email protected]
| | | -- [email protected] | | +-- [email protected] | | | +-- @tootallnate/[email protected] deduped | | | +-- [email protected] deduped | | | +-- [email protected] deduped | | | +-- [email protected] | | | | +-- @tootallnate/[email protected] deduped | | | | +-- [email protected] | | | | +-- [email protected] deduped | | | | +-- [email protected] | | | | +-- [email protected] | | | | | +-- [email protected] deduped | | | | | +-- [email protected] | | | | | |
-- [email protected] deduped
| | | | | -- [email protected] | | | |
-- [email protected]
| | | | +-- [email protected]
| | | | | +-- [email protected] deduped
| | | | | +-- [email protected] deduped
| | | | | +-- [email protected]
| | | | | -- [email protected] | | | |
-- [email protected]
| | | +-- [email protected] deduped
| | | +-- [email protected] deduped
| | | +-- [email protected]
| | | | +-- [email protected]
| | | | | +-- [email protected]
| | | | | | -- [email protected] | | | | | +-- [email protected] | | | | | | +-- [email protected] deduped | | | | | | +-- [email protected] | | | | | | +-- [email protected] | | | | | | +-- [email protected] | | | | | | | +-- [email protected] | | | | | | | +-- [email protected] | | | | | | | +-- [email protected] | | | | | | | | +-- [email protected] deduped | | | | | | | |
-- [email protected] deduped
| | | | | | | +-- [email protected]
| | | | | | | +-- [email protected]
| | | | | | | | -- [email protected] deduped | | | | | | |
-- [email protected]
| | | | | | -- [email protected] deduped | | | | |
-- [email protected]
| | | | +-- [email protected]
| | | | -- [email protected] | | | +-- [email protected] | | | | +-- [email protected] | | | | +-- [email protected] | | | | | +-- [email protected] | | | | | +-- [email protected] deduped | | | | | +-- [email protected] | | | | | +-- [email protected] | | | | |
-- [email protected]
| | | | +-- [email protected]
| | | | | -- [email protected] | | | |
-- [email protected]
| | | -- [email protected] deduped | | +-- [email protected] | |
-- [email protected]
| | +-- [email protected] deduped
| | +-- [email protected] deduped
| | -- [email protected] | | +-- [email protected] deduped | |
-- [email protected]
| +-- [email protected]
| | -- [email protected] | |
-- [email protected]
| +-- [email protected]
| | +-- [email protected]
| | -- [email protected] | +-- [email protected] | | +-- [email protected] | | | +-- [email protected] deduped | | | +-- [email protected] | | | +-- [email protected] | | |
-- [email protected]
| | | -- [email protected] | | +-- [email protected] | | |
-- [email protected]
| | | +-- [email protected]
| | | -- [email protected] | | | +-- [email protected] deduped | | | +-- [email protected] | | | |
-- [email protected] deduped
| | | -- [email protected] | | +-- [email protected] | | +-- [email protected] | | +-- [email protected] | | +-- [email protected] | | +-- [email protected] | | +-- [email protected] | | | +-- [email protected] deduped | | | +-- [email protected] | | |
-- [email protected] deduped
| | -- [email protected] deduped | +-- [email protected] | +-- [email protected] | | +-- [email protected] | | |
-- [email protected]
| | | -- [email protected] | | +-- [email protected] deduped | |
-- [email protected]
| | -- [email protected] | +-- [email protected] |
-- [email protected]
| +-- [email protected]
| | +-- [email protected] deduped
| | +-- [email protected] deduped
| | -- [email protected] deduped | +-- [email protected] | +-- [email protected] | +-- [email protected] | +-- [email protected] deduped | +-- [email protected] |
-- [email protected]
+-- [email protected]
| `-- [email protected]
When I try to run cdk synth
or cdk deploy
, I get the following error.
> "cdk synth"
/Users/tim/workplace/ma-mono/common/temp/node_modules/.pnpm/[email protected]_ff8e2a29703a7cffac9ed3bbb4473395/node_modules/cdk-iam-floyd/lib/shared/policy-statement/6-principals.js:29
this.principals = {};
^
TypeError: Cannot set property principals of [object Object] which has only a getter
at new PolicyStatementWithPrincipal (/Users/tim/workplace/ma-mono/common/temp/node_modules/.pnpm/[email protected]_ff8e2a29703a7cffac9ed3bbb4473395/node_modules/cdk-iam-floyd/lib/shared/policy-statement/6-principals.js:29:25)
This is what my package.json
looks like
"dependencies": {
"aws-cdk-lib": "^2.0.0",
"constructs": "^10.0.0",
"cdk-ssm-document": "^3.1.0",
"cdk-iam-floyd": "^0.300.0",
},
This is what my code looks like
private _createSMDocuments(): void {
const cfnDoc = new Document(this._stack, 'SSMDoc', {
name: `${this._stack.stackName}-SSMDoc`,
documentType: 'Automation',
content: fs
.readFileSync(join(__dirname, `../../src/SSM.yaml`), 'utf8')
.toString()
});
}
If I set aws-cdk-lib
to be explicitly 2.0.0
, I no longer get the error.
"dependencies": {
"aws-cdk-lib": "2.0.0",
"constructs": "^10.0.0",
"cdk-ssm-document": "^3.1.0",
"cdk-iam-floyd": "^0.300.0",
},
Similar issue to #14, this is valid JSON for a choice step assuming that DoSomething
was defined as Boolean input parameter:
{
"name": "DoSomethingCheck",
"action": "aws:branch",
"inputs": {
"Choices": [
{
"NextStep": "DoSomething",
"Variable": "{{DoSomething}}",
"BooleanEquals": true
},
{
"NextStep": "DoSomethingElse",
"Variable": "{{DoSomething}}",
"BooleanEquals": false
}
]
}
},
This fails for the same reason: "Failed to update resource. Input true is of type String, but expected type is Boolean."
Add some logging of the event that is sent to the lambda as well as the request objects that are sent to the api calls.
When debugging a misconfigured json blob elements mainSteps
and its' children there are not enough details to understand the failure.
Current details are only this:
022-02-07T14:07:42.451Z c7bcb752-d1ba-423c-a527-4d4d64cf1150 ERROR InvalidDocumentContent: JSON not well-formed. at Line: 1, Column: 610
at Request.extractError (/var/runtime/node_modules/aws-sdk/lib/protocol/json.js:52:27)
at Request.callListeners (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:106:20)
at Request.emit (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:78:10)
at Request.emit (/var/runtime/node_modules/aws-sdk/lib/request.js:688:14)
at Request.transition (/var/runtime/node_modules/aws-sdk/lib/request.js:22:10)
at AcceptorStateMachine.runTo (/var/runtime/node_modules/aws-sdk/lib/state_machine.js:14:12)
at /var/runtime/node_modules/aws-sdk/lib/state_machine.js:26:10
at Request.<anonymous> (/var/runtime/node_modules/aws-sdk/lib/request.js:38:9)
at Request.<anonymous> (/var/runtime/node_modules/aws-sdk/lib/request.js:690:12)
at Request.callListeners (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:116:18) { code: 'InvalidDocumentContent', time: 2022-02-07T14:07:42.448Z, requestId: 'b35ffedf-86ad-4e56-b889-dfe75f290c79', statusCode: 400, retryable: false, retryDelay: 61.14163968992787} InvalidDocumentContent: JSON not well-formed. at Line: 1, Column: 610
at Request.extractError (/var/runtime/node_modules/aws-sdk/lib/protocol/json.js:52:27)
at Request.callListeners (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:106:20)
at Request.emit (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:78:10)
at Request.emit (/var/runtime/node_modules/aws-sdk/lib/request.js:688:14)
at Request.transition (/var/runtime/node_modules/aws-sdk/lib/request.js:22:10)
at AcceptorStateMachine.runTo (/var/runtime/node_modules/aws-sdk/lib/state_machine.js:14:12)
at /var/runtime/node_modules/aws-sdk/lib/state_machine.js:26:10
at Request.<anonymous> (/var/runtime/node_modules/aws-sdk/lib/request.js:38:9)
at Request.<anonymous> (/var/runtime/node_modules/aws-sdk/lib/request.js:690:12)
at Request.callListeners (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:116:18)
Can you give some more instructions on the prerequisites required to run the lambda/build script for someone with no dev environment?
Cannot create a SSM Document that can be used with AWS Distributor since attachments cannot be added to the definition.
See an example of what the SSM Document looks like for a Distributor package using Cloudformation:
Happy to create a PR to implement this.
When trying to use python with an inline definition it fails with the following message.
1:41:57 PM | CREATE_FAILED | Custom::SSM-Document | SSMDocumentHelloWorldE1940275
Received response status [FAILED] from custom resource. Message returned: Missing "action" in step detail. at Line: 1, Column:
166 | Full error in CloudWatch 2022/02/06/[$LATEST]903dbd363cb440a19d79c087dc5fac00 (RequestId: 4155a91d-ee94-4920-b010-d95af0
861ea1)
Typescript definition for mainSteps is as follows :
/**
* Steps include one or more actions, an optional precondition, a unique name of the action, and inputs (parameters) for those actions.
*
* For more information about documents, including information about creating documents and the differences between schema versions, see https://docs.aws.amazon.com/systems-manager/latest/userguide/ssm-plugins.html
*/
export interface DocumentMainStep {
[key: string]: any;
}
This does not translate into anything from jsii into python. Below is the generated python code.
@jsii.data_type(
jsii_type="cdk-ssm-document.DocumentMainStep",
jsii_struct_bases=[],
name_mapping={},
)
class DocumentMainStep:
def __init__(self) -> None:
'''Steps include one or more actions, an optional precondition, a unique name of the action, and inputs (parameters) for those actions.
For more information about documents, including information about creating documents and the differences between schema versions, see https://docs.aws.amazon.com/systems-manager/latest/userguide/ssm-plugins.html
'''
self._values: typing.Dict[str, typing.Any] = {}
def __eq__(self, rhs: typing.Any) -> builtins.bool:
return isinstance(rhs, self.__class__) and rhs._values == self._values
def __ne__(self, rhs: typing.Any) -> builtins.bool:
return not (rhs == self)
def __repr__(self) -> str:
return "DocumentMainStep(%s)" % ", ".join(
k + "=" + repr(v) for k, v in self._values.items()
)
from aws_cdk import (
Stack,
)
import json
from constructs import Construct
from cdk_ssm_document import DocumentContent, DocumentParameter, DocumentMainStep
import aws_cdk as cdk
from constructs import Construct
from cdk_ssm_document import Document
class DoingThingsStack(Stack):
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
super().__init__(scope, construct_id, **kwargs)
Document(
self,
"SSM-Document-HelloWorld",
name="HelloWorld",
# content=json.dumps(
# dict(
# schemaVersion="2.2",
# description="Echo Hello World!",
# parameters={
# "text": dict(
# default="Hello World!",
# description="Text to echo",
# type="String",
# )
# },
# mainSteps=[
# {
# "name": "echo",
# "action": "aws:runShellScript",
# "inputs": {
# "runCommand": ['echo "THIS WORKS {{text}}"'],
# },
# "precondition": {"StringEquals": ["platformType", "Linux"]},
# }
# ],
# )
# ),
content=DocumentContent(
schema_version="2.2",
description="Echo Hello World!",
parameters={
"text": DocumentParameter(
default="Hello World!",
description="Text to echo",
type="String",
)
},
main_steps=[
{
"name": "echo",
"action": "aws:runShellScript",
"inputs": {"run_command": ['echo "DOESNT WORK {{text}}"']},
"precondition": {"StringEquals": ["platformType", "Linux"]},
}
],
),
)
Commented out version works but its cheating in that it's just building a string and passing it to content
which will take the json/yaml and turn it into an object. Which I suspect works b/c the yaml -> object conversion will just set anything on the internal _values
property.
Instead of using a dynamic key/value pair at a minimum have the interface outline the top level property keys. Would look something like this. All would be set as optional since mainStep varies depending on the document/automation/command you are building out.
We would also leave the [key: string]: any;
as it should allow it to also contain any other property that is needed but we can make the lives of the library users nicer with some auto complete and well make python just work :)
export interface DocumentMainStep {
readonly name?: string;
readonly action?: string;
readonly inputs?: any;
readonly precondition?: any;
readonly outputs?: any;
readonly maxAttempts?: number;
readonly timeoutSeconds?: number;
readonly isCritical?: boolean;
readonly isEnd?: boolean;
readonly onCancel?: string;
readonly onFailure?: string;
readonly nextStep?: string;
[key: string]: any;
}
inputs
, precondition
and outputs
are all marked as any
and are just json blobs that can differ in may ways. inputs
especially.
Pulled these properties from a few places
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.