Ejemplo n.º 1
0
        //parameter
        public override void OutAParameter(AParameter node)
        {
            Definition typeDef, varDef;
            String     typeName = node.GetType().Text;
            String     varName  = node.GetName().Text;

            //    check type name is defined
            if (!_currentSymbolTable.TryGetValue(typeName, out typeDef))
            {
                Console.WriteLine("[" + node.GetType().Line + "] : " + typeName + " is not defined.");

                //    check if type name is defined as a type
            }
            else if (!(typeDef is TypeDefinition))
            {
                Console.WriteLine("[" + node.GetType().Line + "] : " + typeName + " is not a valid type.");

                //    check var name is not defined
            }
            else if (_currentSymbolTable.TryGetValue(varName, out varDef) || _globalSymbolTable.TryGetValue(varName, out varDef))
            {
                Console.WriteLine("[" + node.GetName().Line + "] : " + varName + " is already defined.");

                //    add to symbol table
            }
            else
            {
                VariableDefinition newDef = new VariableDefinition();
                newDef.name    = varName;
                newDef.vartype = (TypeDefinition)typeDef;
                _currentSymbolTable.Add(varName, newDef);
                _currentParamList.Add(newDef);
            }
        }
Ejemplo n.º 2
0
        public IList <AParameter> ConvertParameters(
            IList <ParameterNode> parameters,
            string resourcePrefix = ""
            )
        {
            var resultList = new List <AParameter>();

            if ((parameters == null) || !parameters.Any())
            {
                return(resultList);
            }

            // convert all parameters
            var index = 0;

            foreach (var parameter in parameters)
            {
                ++index;
                var        parameterName     = parameter.Name ?? $"[{index}]";
                AParameter result            = null;
                var        parameterFullName = resourcePrefix + parameter.Name;
                AtLocation(parameterName, () => {
                    if (parameter.Secret != null)
                    {
                        // encrypted value
                        AtLocation("Secret", () => {
                            result = new SecretParameter {
                                Name              = parameter.Name,
                                Description       = parameter.Description,
                                Secret            = parameter.Secret,
                                Export            = parameter.Export,
                                EncryptionContext = parameter.EncryptionContext
                            };
                        });
                    }
                    else if (parameter.Values != null)
                    {
                        // list of values
                        AtLocation("Values", () => {
                            result = new StringListParameter {
                                Name        = parameter.Name,
                                Description = parameter.Description,
                                Values      = parameter.Values,
                                Export      = parameter.Export
                            };
                        });

                        // TODO (2018-08-19, bjorg): this implementation creates unnecessary parameters
                        if (parameter.Resource != null)
                        {
                            AtLocation("Resource", () => {
                                // enumerate individual values with resource definition for each
                                parameter.Parameters = new List <ParameterNode>();
                                for (var i = 1; i <= parameter.Values.Count; ++i)
                                {
                                    parameter.Parameters.Add(new ParameterNode {
                                        Name     = $"Index{i}",
                                        Value    = parameter.Values[i - 1],
                                        Resource = parameter.Resource
                                    });
                                }
                            });
                        }
                    }
                    else if (parameter.Package != null)
                    {
                        // package value
                        result = new PackageParameter {
                            Name        = parameter.Name,
                            Description = parameter.Description,
                            DestinationBucketParameterName = parameter.Package.Bucket,
                            DestinationKeyPrefix           = parameter.Package.Prefix ?? "",
                            PackagePath = parameter.Package.PackagePath
                        };
                    }
                    else if (parameter.Value != null)
                    {
                        if (parameter.Resource != null)
                        {
                            AtLocation("Resource", () => {
                                // existing resource
                                var resource = ConvertResource((string)parameter.Value, parameter.Resource);
                                result       = new ReferencedResourceParameter {
                                    Name        = parameter.Name,
                                    Description = parameter.Description,
                                    Resource    = resource
                                };
                            });
                        }
                        else if (parameter.Value is string text)
                        {
                            // plaintext value
                            result = new StringParameter {
                                Name        = parameter.Name,
                                Description = parameter.Description,
                                Value       = text
                            };
                        }
                        else
                        {
                            // plaintext value
                            result = new ExpressionParameter {
                                Name        = parameter.Name,
                                Description = parameter.Description,
                                Expression  = parameter.Value
                            };
                        }
                    }
                    else if (parameter.Resource != null)
                    {
                        // managed resource
                        AtLocation("Resource", () => {
                            result = new CloudFormationResourceParameter {
                                Name        = parameter.Name,
                                Description = parameter.Description,
                                Resource    = ConvertResource(null, parameter.Resource)
                            };
                        });
                    }
                });

                // check if there are nested parameters
                if (parameter.Parameters != null)
                {
                    AtLocation("Parameters", () => {
                        var nestedParameters = ConvertParameters(
                            parameter.Parameters,
                            parameterFullName
                            );

                        // keep nested parameters only if they have values
                        if (nestedParameters.Any())
                        {
                            // create empty string parameter if collection has no value
                            result = result ?? new StringParameter {
                                Name        = parameter.Name,
                                Value       = "",
                                Description = parameter.Description,
                                Export      = parameter.Export
                            };
                            result.Parameters = nestedParameters;
                        }
                    });
                }

                // add parameter
                if (result != null)
                {
                    result.FullName = parameterFullName;
                    result.Export   = parameter.Export;
                    resultList.Add(result);
                }
            }
            return(resultList);
        }
Ejemplo n.º 3
0
        private void AddParameter(
            AParameter parameter,
            string envPrefix,
            IDictionary <string, object> environmentRefVariables
            )
        {
            object exportValue = null;
            var    fullEnvName = envPrefix + parameter.Name.ToUpperInvariant();

            switch (parameter)
            {
            case SecretParameter secretParameter:
                if (secretParameter.EncryptionContext?.Any() == true)
                {
                    environmentRefVariables["SEC_" + fullEnvName] = $"{secretParameter.Secret}|{string.Join("|", secretParameter.EncryptionContext.Select(kv => $"{Uri.EscapeDataString(kv.Key)}={Uri.EscapeDataString(kv.Value)}"))}";
                }
                else
                {
                    environmentRefVariables["SEC_" + fullEnvName] = secretParameter.Secret;
                }
                break;

            case StringParameter stringParameter:
                environmentRefVariables["STR_" + fullEnvName] = stringParameter.Value;
                exportValue = stringParameter.Value;

                // add literal string parameter value as CloudFormation parameter so it can be referenced
                _stack.Add(stringParameter.FullName, new Parameter {
                    Type        = "String",
                    Default     = stringParameter.Value,
                    Description = stringParameter.Description
                });
                break;

            case StringListParameter stringListParameter: {
                var commaDelimitedValue = string.Join(",", stringListParameter.Values);
                environmentRefVariables["STR_" + fullEnvName] = commaDelimitedValue;
                exportValue = commaDelimitedValue;
            }

                // add literal string list parameter value as CloudFormation parameter so it can be referenced
                _stack.Add(stringListParameter.FullName, new Parameter {
                    Type        = "CommaDelimitedList",
                    Default     = string.Join(",", stringListParameter.Values),
                    Description = stringListParameter.Description
                });
                break;

            case PackageParameter packageParameter:
                environmentRefVariables["STR_" + fullEnvName] = Fn.GetAtt(parameter.FullName, "Result");
                _stack.Add(packageParameter.FullName, new Model.CustomResource("Custom::LambdaSharpS3PackageLoader")
                {
                    ["ServiceToken"]          = Settings.S3PackageLoaderCustomResourceTopicArn,
                    ["DestinationBucketName"] = Humidifier.Fn.Ref(packageParameter.DestinationBucketParameterName),
                    ["DestinationKeyPrefix"]  = packageParameter.DestinationKeyPrefix,
                    ["SourceBucketName"]      = Settings.DeploymentBucketName,
                    ["SourcePackageKey"]      = $"{_module.Name}/{Path.GetFileName(packageParameter.PackagePath)}"
                });
                break;

            case ExpressionParameter expressionParameter:
                environmentRefVariables["STR_" + fullEnvName] = expressionParameter.Expression;
                exportValue = expressionParameter.Expression;
                break;

            case ReferencedResourceParameter referenceResourceParameter: {
                var resource = referenceResourceParameter.Resource;
                environmentRefVariables["STR_" + fullEnvName] = resource.ResourceArn;
                exportValue = resource.ResourceArn;

                // add permissions for resource
                if (resource.Allow?.Any() == true)
                {
                    _resourceStatements.Add(new Statement {
                            Sid      = parameter.FullName,
                            Effect   = "Allow",
                            Resource = resource.ResourceArn,
                            Action   = resource.Allow
                        });
                }

                // add reference resource parameter value as CloudFormation parameter so it can be referenced
                _stack.Add(referenceResourceParameter.FullName, new Parameter {
                        Type        = "String",
                        Default     = resource.ResourceArn,
                        Description = referenceResourceParameter.Description
                    });
            }
            break;

            case CloudFormationResourceParameter cloudFormationResourceParameter: {
                var    resource     = cloudFormationResourceParameter.Resource;
                var    resourceName = parameter.FullName;
                object resourceArn;
                object resourceParamFn;
                Humidifier.Resource resourceTemplate;
                if (resource.Type.StartsWith("Custom::"))
                {
                    resourceArn      = null;
                    resourceParamFn  = Fn.GetAtt(resourceName, "Result");
                    resourceTemplate = new Model.CustomResource(resource.Type, resource.Properties);
                }
                else if (!Settings.ResourceMapping.TryParseResourceProperties(
                             resource.Type,
                             resourceName,
                             resource.Properties,
                             out resourceArn,
                             out resourceParamFn,
                             out resourceTemplate
                             ))
                {
                    throw new NotImplementedException($"resource type is not supported: {resource.Type}");
                }
                _stack.Add(resourceName, resourceTemplate, dependsOn: resource.DependsOn.ToArray());
                exportValue = resourceParamFn;

                // only add parameters that the lambda functions are allowed to access
                if (resource.Type.StartsWith("Custom::") || (resource.Allow?.Any() == true))
                {
                    environmentRefVariables["STR_" + fullEnvName] = resourceParamFn;
                }

                // add permissions for resource
                if ((resourceArn != null) && (resource.Allow?.Any() == true))
                {
                    _resourceStatements.Add(new Statement {
                            Sid      = parameter.FullName,
                            Effect   = "Allow",
                            Resource = resourceArn,
                            Action   = resource.Allow
                        });
                }
            }
            break;

            default:
                throw new ArgumentOutOfRangeException(nameof(parameter), parameter, "unknown parameter type");
            }

            // check if nested parameters need to be added
            if (parameter.Parameters?.Any() == true)
            {
                foreach (var nestedResource in parameter.Parameters)
                {
                    AddParameter(
                        nestedResource,
                        fullEnvName + "_",
                        environmentRefVariables
                        );
                }
            }

            // check if resource name should be exported
            if (parameter.Export != null)
            {
                var export = parameter.Export.StartsWith("/")
                    ? parameter.Export
                    : $"/{Settings.Tier}/{_module.Name}/{parameter.Export}";
                _stack.Add(parameter.FullName + "SsmParameter", new SSM.Parameter {
                    Name        = export,
                    Description = parameter.Description,
                    Type        = "String",
                    Value       = exportValue
                });
            }
        }
Ejemplo n.º 4
0
        private void AddParameter(
            AParameter parameter,
            string envPrefix,
            IDictionary <string, object> environmentRefVariables
            )
        {
            object exportValue = null;
            var    fullEnvName = envPrefix + parameter.Name.ToUpperInvariant();

            switch (parameter)
            {
            case SecretParameter secretParameter:
                if (secretParameter.Export != null)
                {
                    // TODO (2018-08-16, bjorg): add support for exporting secrets (or error out sooner)
                    throw new NotImplementedException("exporting secrets is not yet supported");
                }
                break;

            case CollectionParameter collectionParameter: {
                foreach (var nestedResource in collectionParameter.Parameters)
                {
                    AddParameter(
                        nestedResource,
                        fullEnvName + "_",
                        environmentRefVariables
                        );
                }
                if (collectionParameter.Export != null)
                {
                    // TODO (2018-08-16, bjorg): add support for exporting collections (or error out sooner)
                    throw new NotImplementedException("exporting collections is not yet supported");
                }
            }
            break;

            case StringParameter stringParameter:
                exportValue = stringParameter.Value;
                break;

            case PackageParameter packageParameter:
                environmentRefVariables[fullEnvName] = Fn.GetAtt(parameter.FullName, "Result");
                _stack.Add(packageParameter.FullName, new Model.CustomResource("Custom::LambdaSharpS3PackageLoader", new Dictionary <string, object> {
                    ["ServiceToken"]          = _module.Settings.S3PackageLoaderCustomResourceTopicArn,
                    ["DestinationBucketName"] = Humidifier.Fn.Ref(packageParameter.Bucket),
                    ["DestinationKeyPrefix"]  = packageParameter.Prefix,
                    ["SourceBucketName"]      = _module.Settings.DeploymentBucketName,
                    ["SourcePackageKey"]      = packageParameter.PackageS3Key,
                }));
                break;

            case ReferencedResourceParameter referenceResourceParameter: {
                var resource = referenceResourceParameter.Resource;
                exportValue = resource.ResourceArn;

                // add permissions for resource
                if (resource.Allow?.Any() == true)
                {
                    _resourceStatements.Add(new Statement {
                            Effect   = "Allow",
                            Resource = resource.ResourceArn,
                            Action   = resource.Allow
                        });
                }
            }
            break;

            case CloudFormationResourceParameter cloudFormationResourceParameter: {
                var    resource     = cloudFormationResourceParameter.Resource;
                var    resourceName = parameter.FullName;
                object resourceArn;
                object resourceParamFn;
                Humidifier.Resource resourceTemplate;
                if (resource.Type.StartsWith("Custom::"))
                {
                    resourceArn      = null;
                    resourceParamFn  = Fn.GetAtt(resourceName, "Result");
                    resourceTemplate = new Model.CustomResource(resource.Type, resource.Properties);
                }
                else if (!_module.Settings.ResourceMapping.TryParseResourceProperties(
                             resource.Type,
                             resourceName,
                             resource.Properties,
                             out resourceArn,
                             out resourceParamFn,
                             out resourceTemplate
                             ))
                {
                    throw new NotImplementedException($"resource type is not supported: {resource.Type}");
                }

                // for S3 buckets, we need to check if any functions use the bucket as an event source
                if (resource.Type == "AWS::S3::Bucket")
                {
                    var s3Template = (Humidifier.S3.Bucket)resourceTemplate;
                    var s3Sources  = _module.Functions.SelectMany(function => function.Sources
                                                                  .OfType <S3Source>()
                                                                  .Where(source => source.Bucket == resourceName)
                                                                  .Select(source => new {
                            Function = function,
                            Source   = source
                        })
                                                                  )
                                     .ToList();
                    if (s3Sources.Any())
                    {
                        // NOTE (2018-06-28, bjorg): for S3 buckets, we need to jump through a few hoops to make
                        //      everything work as expected; first, we need to know the final name of the bucket;
                        //      second, we cannot use `Ref()` to get its name, because it introduces a circular dependency.

                        // check if we need to create a hashed bucket name and set `BucketName` in template
                        if (s3Template.BucketName == null)
                        {
                            // NOTE (2018-08-16, bjorg): bucket names must be lowercase
                            var bucketName = $"{_module.Settings.Tier}-{_module.Name}-{resourceName}-".ToLowerInvariant();
                            bucketName           += $"{_module.Settings.AwsAccountId}-{_module.Settings.AwsRegion}-{bucketName}".ToMD5Hash().Substring(0, 7).ToLowerInvariant();
                            s3Template.BucketName = bucketName;
                            var arn = $"arn:aws:s3:::{bucketName}";
                            resourceArn = new object[] {
                                arn,
                                arn + "/*"
                            };
                            foreach (var src in s3Sources)
                            {
                                src.Source.BucketArn = arn;
                            }
                        }

                        // use the hashed bucket name as environment variable
                        resourceParamFn = s3Template.BucketName;

                        // add notification configuration to template
                        s3Template.NotificationConfiguration = new Humidifier.S3.BucketTypes.NotificationConfiguration {
                            LambdaConfigurations = s3Sources.SelectMany(src => src.Source.Events.Select(evt => new Humidifier.S3.BucketTypes.LambdaConfiguration {
                                    Event    = evt,
                                    Filter   = ConvertFilter(src.Source.Prefix, src.Source.Suffix),
                                    Function = Fn.GetAtt(src.Function.Name, "Arn")
                                })).ToList()
                        };
                    }

                    // local function
                    Humidifier.S3.BucketTypes.NotificationFilter ConvertFilter(string prefix, string suffix)
                    {
                        if ((prefix == null) && (suffix == null))
                        {
                            return(null);
                        }
                        var rules = new List <Humidifier.S3.BucketTypes.FilterRule>();

                        if (prefix != null)
                        {
                            rules.Add(new Humidifier.S3.BucketTypes.FilterRule {
                                    Name  = "prefix",
                                    Value = prefix
                                });
                        }
                        if (suffix != null)
                        {
                            rules.Add(new Humidifier.S3.BucketTypes.FilterRule {
                                    Name  = "suffix",
                                    Value = suffix
                                });
                        }
                        return(new Humidifier.S3.BucketTypes.NotificationFilter {
                                S3Key = new Humidifier.S3.BucketTypes.S3KeyFilter {
                                    Rules = rules
                                }
                            });
                    }
                }
                _stack.Add(resourceName, resourceTemplate);
                exportValue = resourceParamFn;

                // only add parameters that the lambda functions are allowed to access
                if (resource.Type.StartsWith("Custom::") || (resource.Allow?.Any() == true))
                {
                    environmentRefVariables[fullEnvName] = resourceParamFn;
                }

                // add permissions for resource
                if ((resourceArn != null) && (resource.Allow?.Any() == true))
                {
                    _resourceStatements.Add(new Statement {
                            Effect   = "Allow",
                            Resource = resourceArn,
                            Action   = resource.Allow
                        });
                }
            }
            break;

            default:
                throw new ArgumentOutOfRangeException(nameof(parameter), parameter, "unknown parameter type");
            }

            // check if resource name should be exported
            if (parameter.Export != null)
            {
                var export = parameter.Export.StartsWith("/")
                    ? parameter.Export
                    : $"/{_module.Settings.Tier}/{_module.Name}/{parameter.Export}";
                _stack.Add(parameter.FullName + "SsmParameter", new SSM.Parameter {
                    Name        = export,
                    Description = parameter.Description,
                    Type        = "String",
                    Value       = exportValue
                });
            }
        }