include::../description.adoc[]

include::../ask-yourself.adoc[]

include::../recommended.adoc[]

== Sensitive Code Example

[source,python]
----
url = "http://example.com" # Sensitive
url = "ftp://anonymous@example.com" # Sensitive
url = "telnet://anonymous@example.com" # Sensitive

import telnetlib
cnx = telnetlib.Telnet("towel.blinkenlights.nl") # Sensitive

import ftplib
cnx = ftplib.FTP("ftp.example.com") # Sensitive

import smtplib
smtp = smtplib.SMTP("smtp.example.com", port=587) # Sensitive
----

For https://docs.aws.amazon.com/cdk/api/v2/python/aws_cdk.aws_elasticloadbalancingv2/ApplicationLoadBalancer.html[aws_cdk.aws_elasticloadbalancingv2.ApplicationLoadBalancer]:

[source,python]
----
from aws_cdk import (
    aws_elasticloadbalancingv2 as elbv2,
)

lb = elbv2.ApplicationLoadBalancer(
    self,
    "LB",
    vpc=vpc,
    internet_facing=True
)

lb.add_listener(
    "Listener-default",
    port=80, # Sensitive
    open=True
)
lb.add_listener(
    "Listener-http-explicit",
    protocol=elbv2.ApplicationProtocol.HTTP, # Sensitive
    port=8080,
    open=True
)
----

For https://docs.aws.amazon.com/cdk/api/v2/python/aws_cdk.aws_elasticloadbalancingv2/ApplicationListener.html[aws_cdk.aws_elasticloadbalancingv2.ApplicationListener]:

[source,python]
----
from aws_cdk import (
    aws_elasticloadbalancingv2 as elbv2,
)

elbv2.ApplicationListener(
    self,
    "listener-http-explicit-const",
    load_balancer=lb,
    protocol=elbv2.ApplicationProtocol.HTTP, # Sensitive
    port=8081,
    open=True
)
----

For https://docs.aws.amazon.com/cdk/api/v2/python/aws_cdk.aws_elasticloadbalancingv2/NetworkLoadBalancer.html[aws_cdk.aws_elasticloadbalancingv2.NetworkLoadBalancer]:

[source,python]
----
from aws_cdk import (
    aws_elasticloadbalancingv2 as elbv2,
)
lb = elbv2.NetworkLoadBalancer(
    self,
    "LB",
    vpc=vpc,
    internet_facing=True
)

lb.add_listener( # Sensitive
    "Listener-default",
    port=1234
)
lb.add_listener(
    "Listener-TCP-explicit",
    protocol=elbv2.Protocol.TCP, # Sensitive
    port=1337
)
----

For https://docs.aws.amazon.com/cdk/api/v2/python/aws_cdk.aws_elasticloadbalancingv2/NetworkListener.html[aws_cdk.aws_elasticloadbalancingv2.NetworkListener]:

[source,python]
----
from aws_cdk import (
    aws_elasticloadbalancingv2 as elbv2,
)

elbv2.NetworkListener(
    self,
    "Listener-TCP-explicit",
    protocol=elbv2.Protocol.TCP, # Sensitive
    port=1338,
    load_balancer=lb
)
----

For https://docs.aws.amazon.com/cdk/api/v2/python/aws_cdk.aws_elasticloadbalancingv2/CfnListener.html[aws_cdk.aws_elasticloadbalancingv2.CfnListener]:

[source,python]
----
from aws_cdk import (
    aws_elasticloadbalancingv2 as elbv2,
)

elbv2.CfnListener(
    self,
    "listener-http",
    default_actions=[application_default_action],
    load_balancer_arn=lb.load_balancer_arn,
    protocol="HTTP", # Sensitive
    port=80
)

elbv2.CfnListener(
    self,
    "listener-tcp",
    default_actions=[network_default_action],
    load_balancer_arn=lb.load_balancer_arn,
    protocol="TCP", # Sensitive
    port=1000
)
----

For https://docs.aws.amazon.com/cdk/api/v2/python/aws_cdk.aws_elasticloadbalancing/LoadBalancerListener.html[aws_cdk.aws_elasticloadbalancing.LoadBalancerListener]:

[source,python]
----
from aws_cdk import (
    aws_elasticloadbalancing as elb,
)

elb.LoadBalancerListener(
    external_port=10000,
    external_protocol=elb.LoadBalancingProtocol.TCP, # Sensitive
    internal_port=10000
)

elb.LoadBalancerListener(
    external_port=10080,
    external_protocol=elb.LoadBalancingProtocol.HTTP, # Sensitive
    internal_port=10080
)
----

For https://docs.aws.amazon.com/cdk/api/v2/python/aws_cdk.aws_elasticloadbalancing/CfnLoadBalancer.html[aws_cdk.aws_elasticloadbalancing.CfnLoadBalancer]:

[source, python]
----
from aws_cdk import (
    aws_elasticloadbalancing as elb
)

elb.CfnLoadBalancer(
    self,
    "elb-tcp",
    listeners=[
        elb.CfnLoadBalancer.ListenersProperty(
            instance_port="10000",
            load_balancer_port="10000",
            protocol="tcp" # Sensitive
        )
    ],
    subnets=vpc.select_subnets().subnet_ids
)

elb.CfnLoadBalancer(
    self,
    "elb-http-dict",
    listeners=[
        {
            "instancePort":"10000",
            "loadBalancerPort":"10000",
            "protocol":"http" # Sensitive
        }
    ],
    subnets=vpc.select_subnets().subnet_ids
)
----

For https://docs.aws.amazon.com/cdk/api/v2/python/aws_cdk.aws_elasticloadbalancing/LoadBalancer.html[aws_cdk.aws_elasticloadbalancing.LoadBalancer]:

[source,python]
----
from aws_cdk import (
    aws_elasticloadbalancing as elb,
)

elb.LoadBalancer(
    self,
    "elb-tcp-dict",
    vpc=vpc,
    listeners=[
        {
            "externalPort":10000,
            "externalProtocol":elb.LoadBalancingProtocol.TCP, # Sensitive
            "internalPort":10000
        }
    ]
)

loadBalancer.add_listener(
    external_port=10081,
    external_protocol=elb.LoadBalancingProtocol.HTTP, # Sensitive
    internal_port=10081
)
loadBalancer.add_listener(
    external_port=10001,
    external_protocol=elb.LoadBalancingProtocol.TCP, # Sensitive
    internal_port=10001
)
----

For https://docs.aws.amazon.com/cdk/api/v2/python/aws_cdk.aws_elasticache/CfnReplicationGroup.html[aws_cdk.aws_elasticache.CfnReplicationGroup]:

[source,python]
----
from aws_cdk import (
    aws_elasticache as elasticache
)

elasticache.CfnReplicationGroup(
    self,
    "unencrypted-explicit",
    replication_group_description="a replication group",
    automatic_failover_enabled=False,
    transit_encryption_enabled=False, # Sensitive
    cache_subnet_group_name="test",
    engine="redis",
    engine_version="3.2.6",
    num_cache_clusters=1,
    cache_node_type="cache.t2.micro"
)

elasticache.CfnReplicationGroup( # Sensitive, encryption is disabled by default
    self,
    "unencrypted-implicit",
    replication_group_description="a test replication group",
    automatic_failover_enabled=False,
    cache_subnet_group_name="test",
    engine="redis",
    engine_version="3.2.6",
    num_cache_clusters=1,
    cache_node_type="cache.t2.micro"
) 
----

For https://docs.aws.amazon.com/cdk/api/v2/python/aws_cdk.aws_kinesis/CfnStream.html[aws_cdk.aws_kinesis.CfnStream]:

[source,python]
----
from aws_cdk import (
    aws_kinesis as kinesis,
)

kinesis.CfnStream( # Sensitive, encryption is disabled by default for CfnStreams
    self,
    "cfnstream-implicit-unencrytped",
    shard_count=1
)

kinesis.CfnStream(self,
    "cfnstream-explicit-unencrytped",
    shard_count=1,
    stream_encryption=None # Sensitive
)
----

For https://docs.aws.amazon.com/cdk/api/v2/python/aws_cdk.aws_kinesis/Stream.html[aws_cdk.aws_kinesis.Stream]:

[source,python]
----
from aws_cdk import (
    aws_kinesis as kinesis,
)

stream = kinesis.Stream(self,
    "stream-explicit-unencrypted",
    shard_count=1,
    encryption=kinesis.StreamEncryption.UNENCRYPTED # Sensitive
)
----

== Compliant Solution

[source,python]
----
url = "https://example.com"
url = "sftp://anonymous@example.com"
url = "ssh://anonymous@example.com"

import ftplib
cnx = ftplib.FTP_TLS("ftp.example.com")

import smtplib
smtp = smtplib.SMTP("smtp.example.com", port=587)
smtp.starttls(context=context)

smtp_ssl = smtplib.SMTP_SSL("smtp.gmail.com", port=465)
----

For https://docs.aws.amazon.com/cdk/api/v2/python/aws_cdk.aws_elasticloadbalancingv2/ApplicationLoadBalancer.html[aws_cdk.aws_elasticloadbalancingv2.ApplicationLoadBalancer]:
[source,python]

----
from aws_cdk import (
    aws_elasticloadbalancingv2 as elbv2,
)

lb = elbv2.ApplicationLoadBalancer(
    self,
    "LB",
    vpc=vpc,
    internet_facing=True
)

lb.add_listener(
    "Listener-https-explicit",
    protocol=elbv2.ApplicationProtocol.HTTPS,
    certificates=[elbv2.ListenerCertificate("certificateARN")],
    port=443,
    open=True
)

lb.add_listener(
    "Listener-https-implicit",
    certificates=[elbv2.ListenerCertificate("certificateARN")],
    port=8443,
    open=True
)
----

For https://docs.aws.amazon.com/cdk/api/v2/python/aws_cdk.aws_elasticloadbalancingv2/ApplicationListener.html[ aws_cdk.aws_elasticloadbalancingv2.ApplicationListener]:

[source,python]
----
from aws_cdk import (
    aws_elasticloadbalancingv2 as elbv2,
)

elbv2.ApplicationListener(
    self,
    "listener-https-explicit-const",
    load_balancer=lb,
    protocol=elbv2.ApplicationProtocol.HTTPS,
    certificates=[elbv2.ListenerCertificate("certificateARN")],
    port=444,
    open=True
)
----

For https://docs.aws.amazon.com/cdk/api/v2/python/aws_cdk.aws_elasticloadbalancingv2/NetworkLoadBalancer.html[aws_cdk.aws_elasticloadbalancingv2.NetworkLoadBalancer]:

[source,python]
----
from aws_cdk import (
    aws_elasticloadbalancingv2 as elbv2,
)
lb = elbv2.NetworkLoadBalancer(
    self,
    "LB",
    vpc=vpc,
    internet_facing=True
)

lb.add_listener(
    "Listener-TLS-explicit",
    protocol=elbv2.Protocol.TLS,
    certificates=[elbv2.ListenerCertificate("certificateARN")],
    port=443
)
lb.add_listener(
    "Listener-TLS-implicit",
    certificates=[elbv2.ListenerCertificate("certificateARN")],
    port=1024
)
----

For https://docs.aws.amazon.com/cdk/api/v2/python/aws_cdk.aws_elasticloadbalancingv2/NetworkListener.html[aws_cdk.aws_elasticloadbalancingv2.NetworkListener]:

[source,python]
----
from aws_cdk import (
    aws_elasticloadbalancingv2 as elbv2,
)

elbv2.NetworkListener(
    self,
    "Listener-TLS-explicit",
    protocol=elbv2.Protocol.TLS,
    certificates=[elbv2.ListenerCertificate("certificateARN")],
    port=443,
    load_balancer=lb
)
----

For https://docs.aws.amazon.com/cdk/api/v2/python/aws_cdk.aws_elasticloadbalancingv2/CfnListener.html[aws_cdk.aws_elasticloadbalancingv2.CfnListener]:

[source,python]
----
from aws_cdk import (
    aws_elasticloadbalancingv2 as elbv2,
)

elbv2.CfnListener(
    self,
    "listener-https",
    default_actions=[application_default_action],
    load_balancer_arn=lb.load_balancer_arn,
    protocol="HTTPS",
    port=443,
    certificates=[elbv2.CfnListener.CertificateProperty(
        certificate_arn="certificateARN"
    )]
)

elbv2.CfnListener(
    self,
    "listener-tls",
    default_actions=[network_default_action],
    load_balancer_arn=lb.load_balancer_arn,
    protocol="TLS",
    port=1001,
    certificates=[elbv2.CfnListener.CertificateProperty(
        certificate_arn="certificateARN"
    )]
)
----

For https://docs.aws.amazon.com/cdk/api/v2/python/aws_cdk.aws_elasticloadbalancing/LoadBalancerListener.html[aws_cdk.aws_elasticloadbalancing.LoadBalancerListener]:

[source,python]
----
from aws_cdk import (
    aws_elasticloadbalancing as elb,
)

elb.LoadBalancerListener(
    external_port=10043,
    external_protocol=elb.LoadBalancingProtocol.SSL,
    internal_port=10043,
    ssl_certificate_arn="certificateARN"
)

elb.LoadBalancerListener(
    external_port=10443,
    external_protocol=elb.LoadBalancingProtocol.HTTPS,
    internal_port=10443,
    ssl_certificate_arn="certificateARN"
)
----

For https://docs.aws.amazon.com/cdk/api/v2/python/aws_cdk.aws_elasticloadbalancing/CfnLoadBalancer.html[aws_cdk.aws_elasticloadbalancing.CfnLoadBalancer]:

[source,python]
----
from aws_cdk import (
    aws_elasticloadbalancing as elb,
)

elb.CfnLoadBalancer(
    self,
    "elb-ssl",
    listeners=[
        elb.CfnLoadBalancer.ListenersProperty(
            instance_port="10043",
            load_balancer_port="10043",
            protocol="ssl",
            ssl_certificate_id=CERTIFICATE_ARN
        )
    ],
    subnets=vpc.select_subnets().subnet_ids
)

elb.CfnLoadBalancer(
    self,
    "elb-https-dict",
    listeners=[
        {
            "instancePort":"10443",
            "loadBalancerPort":"10443",
            "protocol":"https",
            "sslCertificateId":CERTIFICATE_ARN
        }
    ],
    subnets=vpc.select_subnets().subnet_ids
)
----

For https://docs.aws.amazon.com/cdk/api/v2/python/aws_cdk.aws_elasticloadbalancing/LoadBalancer.html[aws_cdk.aws_elasticloadbalancing.LoadBalancer]:

[source,python]
----
from aws_cdk import (
    aws_elasticloadbalancing as elb,
)

elb.LoadBalancer(
    self,
    "elb-ssl",
    vpc=vpc,
    listeners=[
        {
            "externalPort":10044,
            "externalProtocol":elb.LoadBalancingProtocol.SSL,
            "internalPort":10044,
            "sslCertificateArn":"certificateARN"
        },
        {
            "externalPort":10444,
            "externalProtocol":elb.LoadBalancingProtocol.HTTPS,
            "internalPort":10444,
            "sslCertificateArn":"certificateARN"
        }
    ]
)

loadBalancer = elb.LoadBalancer(
        self,
        "elb-multi-listener",
        vpc=vpc
)
loadBalancer.add_listener(
    external_port=10045,
    external_protocol=elb.LoadBalancingProtocol.SSL,
    internal_port=10045,
    ssl_certificate_arn="certificateARN"
)
loadBalancer.add_listener(
    external_port=10445,
    external_protocol=elb.LoadBalancingProtocol.HTTPS,
    internal_port=10445,
    ssl_certificate_arn="certificateARN"
)
----

For https://docs.aws.amazon.com/cdk/api/v2/python/aws_cdk.aws_elasticache/CfnReplicationGroup.html[aws_cdk.aws_elasticache.CfnReplicationGroup]:

[source,python]
----
from aws_cdk import (
    aws_elasticache as elasticache
)

elasticache.CfnReplicationGroup(
    self,
    "encrypted-explicit",
    replication_group_description="a test replication group",
    automatic_failover_enabled=False,
    transit_encryption_enabled=True,
    cache_subnet_group_name="test",
    engine="redis",
    engine_version="3.2.6",
    num_cache_clusters=1,
    cache_node_type="cache.t2.micro"
)
----

For https://docs.aws.amazon.com/cdk/api/v2/python/aws_cdk.aws_kinesis/CfnStream.html[aws_cdk.aws_kinesis.CfnStream]:

[source,python]
----
from aws_cdk import (
    aws_kinesis as kinesis,
)

kinesis.CfnStream(
    self,
    "cfnstream-explicit-encrytped",
    shard_count=1,
    stream_encryption=kinesis.CfnStream.StreamEncryptionProperty(
        encryption_type="KMS",
        key_id="alias/aws/kinesis"
    )
)

stream = kinesis.CfnStream(
    self,
    "cfnstream-explicit-encrytped-dict",
    shard_count=1,
    stream_encryption={
        "encryptionType": "KMS",
        "keyId": "alias/aws/kinesis"
    }
)
----

For https://docs.aws.amazon.com/cdk/api/v2/python/aws_cdk.aws_kinesis/Stream.html[aws_cdk.aws_kinesis.Stream]:

[source,python]
----
from aws_cdk import (
    aws_kinesis as kinesis,
    aws_kms as kms
)

stream = kinesis.Stream( # Encryption is enabled by default for Streams
    self,
    "stream-implicit-encrypted",
    shard_count=1
)

stream = kinesis.Stream(
    self,
    "stream-explicit-encrypted-managed",
    shard_count=1,
    encryption=kinesis.StreamEncryption.MANAGED
)

key = kms.Key(self, "managed_key")
stream = kinesis.Stream(
    self,
    "stream-explicit-encrypted-selfmanaged",
    shard_count=1,
    encryption=kinesis.StreamEncryption.KMS,
    encryption_key=key
)
----

include::../exceptions.adoc[]

include::../see.adoc[]


ifdef::env-github,rspecator-view[]

'''
== Implementation Specification
(visible only on this page)

=== Message

* Using {protocol.insecure} protocol is insecure. Use {protocol.alternatives} instead.

* Make sure STARTTLS is used to upgrade to a secure connection using SSL/TLS. 

For `aws_cdk.aws_elasticloadbalancing.LoadBalancer`, `aws_cdk.aws_elasticloadbalancing.CfnLoadBalancer`, `aws_cdk.aws_elasticloadbalancing.LoadBalancerListener`, `aws_cdk.aws_elasticloadbalancingv2.ApplicationLoadBalancer`, `aws_cdk.aws_elasticloadbalancingv2.NetworkLoadBalancer`, `aws_cdk.aws_elasticloadbalancingv2.ApplicationListener`, `aws_cdk.aws_elasticloadbalancingv2.ApplicationListener`, `aws_cdk.aws_elasticloadbalancingv2.NetworkListener` and `aws_cdk.aws_elasticloadbalancingv2.CfnListener`:

* Make sure that using network protocols without an SSL/TLS underlay is safe here.

For `aws_cdk.aws_elasticache.CfnReplicationGroup`:

* Make sure that disabling transit encryption is safe here.

For `aws_cdk.aws_kinesis.CfnStream` and `aws_cdk.aws_kinesis.Stream`: 

* Make sure that disabling stream encryption is safe here.

=== Highlighting

For `aws_cdk.aws_elasticloadbalancingv2.ApplicationLoadBalancer`:

* Highlight the `protocol` parameter of the `add_listener` call when it is set
    to elbv2.ApplicationProtocol.HTTP
* Highlight the `add_listener` call when the `protocol` parameter is not set
    and the port parameter is 80, 8000, 8080 or 8008

For `aws_cdk.aws_elasticloadbalancingv2.ApplicationListener`

* Highlight the `protocol` property of the object constructor when it is set to
    elbv2.ApplicationProtocol.HTTP
* Highlight the object constructor call when the `protocol` parameter is not set
    and the port parameter is 80, 8000, 8080 or 8008

For `aws_cdk.aws_elasticloadbalancingv2.NetworkLoadBalancer`

* Highlight the `protocol` parameter of the `add_listener` call when it is set
    to elbv2.Protocol.TCP, elbv2.Protocol.UDP, or
    elbv2.Protocol.TCP_UDP
* Highlight the `add_listener` call when the `protocol` parameter is not set
    and the `certificates` parameter is not set or is an empty `Sequence`.

For `aws_cdk.aws_elasticloadbalancingv2.NetworkListener`

* Highlight the `protocol` property of the object constructor call when it is set
    to elbv2.ApplicationProtocol.TCP, elbv2.ApplicationProtocol.UDP, or
    elbv2.ApplicationProtocol.TCP_UDP
* Highlight the constructor call when the `protocol` parameter is not set
    and the `certificates` parameter is not set or is an empty `Sequence`.

For `aws_cdk.aws_elasticloadbalancingv2.CfnListener`:

* Highlight the `protocol` property of the object constructor when set to
    HTTP, TCP, UDP, or TCP_UDP.

For `aws_cdk.aws_elasticloadbalancing.LoadBalancer`:

* Highlight the `externalProtocol` dict entry in the `listeners` property of the
    object constructor when set to `elb.LoadBalancingProtocol.TCP` or `elb.LoadBalancingProtocol.HTTP`.
* Highlight the `externalProtocol` parameter of the call to `add_listener` when set to `elb.LoadBalancingProtocol.TCP` or `elb.LoadBalancingProtocol.HTTP`.

For `aws_cdk.aws_elasticloadbalancing.CfnLoadBalancer`:

* When the `listeners` property of the object constructor is a `Sequence`
    that contains a `dict` with a "protocol" entry set to "tcp" or "http",
    highligth the "protocol" entry.
* When the `listeners` property of the object constructor is a `Sequence`
    that contains an `elb.CfnLoadBalancer.ListenersProperty` with a `protocol`
    property set to "tcp" or "http", highlight the protocol property.


For `aws_cdk.aws_elasticloadbalancing.LoadBalancerListener`:

* Highlight the `external_protocol` property of the object constructor when set to `elb.LoadBalancingProtocol.TCP` or `elb.LoadBalancingProtocol.HTTP`.

For `aws_cdk.aws_elasticache.CfnReplicationGroup`:

* Highlight the `transit_encryption_enabled` property of the object constructor if it is
    present and set to False.
* Highlight the constructor call if the `transit_encryption_enabled` attribute is not set.

For `aws_cdk.aws_kinesis.CfnStream`:

* Highlight the object constructor when the `stream_encryption` property is not set.
* Highlight the `stream_encryption` property of the object constructor when set to None.

For `aws_cdk.aws_kinesis.Stream`:

* Highlight the `encryption` property of the object constructor when it is set to aws_kinesis.StreamEncryption.UNENCRYPTED


endif::env-github,rspecator-view[]
