Skip to content

Commit 28c8b02

Browse files
Clee2691openshift-merge-bot[bot]
authored andcommitted
LOG-8006: Can't create networkPolicy for s3 output.
1 parent 080f848 commit 28c8b02

File tree

3 files changed

+237
-12
lines changed

3 files changed

+237
-12
lines changed

bundle/manifests/cluster-logging.clusterserviceversion.yaml

Lines changed: 205 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ metadata:
8282
categories: OpenShift Optional, Logging & Tracing, Observability
8383
certified: "false"
8484
containerImage: quay.io/openshift-logging/cluster-logging-operator:latest
85-
createdAt: "2025-10-10T20:13:29Z"
85+
createdAt: "2025-10-27T15:33:17Z"
8686
description: The Red Hat OpenShift Logging Operator for OCP provides a means for
8787
configuring and managing log collection and forwarding.
8888
features.operators.openshift.io/cnf: "false"
@@ -502,7 +502,8 @@ spec:
502502
logs
503503
displayName: Amazon CloudWatch
504504
path: outputs[0].cloudwatch
505-
- description: Authentication sets credentials for authenticating the requests.
505+
- description: Authentication sets credentials for authenticating requests to
506+
cloudwatch services.
506507
displayName: Authentication Options
507508
path: outputs[0].cloudwatch.authentication
508509
- description: |-
@@ -536,7 +537,14 @@ spec:
536537
path: outputs[0].cloudwatch.authentication.assumeRole.roleARN.secretName
537538
x-descriptors:
538539
- urn:alm:descriptor:com.tectonic.ui:text
539-
- description: AWSAccessKey points to the AWS access key id and secret to be
540+
- description: |-
541+
SessionName is an optional identifier for the assumed role session.
542+
If not provided, a default session name will be generated.
543+
displayName: Session Name
544+
path: outputs[0].cloudwatch.authentication.assumeRole.sessionName
545+
x-descriptors:
546+
- urn:alm:descriptor:com.tectonic.ui:text
547+
- description: AwsAccessKey points to the AWS access key id and secret to be
540548
used for authentication.
541549
displayName: Access Key
542550
path: outputs[0].cloudwatch.authentication.awsAccessKey
@@ -570,7 +578,7 @@ spec:
570578
x-descriptors:
571579
- urn:alm:descriptor:com.tectonic.ui:text
572580
- description: |-
573-
IAMRole points to the secret containing the role ARN to be used for authentication.
581+
IamRole points to the secret containing the role ARN to be used for authentication.
574582
This can be used for authentication in STS-enabled clusters when additionally specifying
575583
a web identity token
576584
displayName: Amazon IAM Role
@@ -728,23 +736,23 @@ spec:
728736
- description: |-
729737
Index is the index for the logs. This supports template syntax to allow dynamic per-event values.
730738
731-
The Index can be a combination of static and dynamic values consisting of field paths followed by `||` followed by another field path or a static value.
739+
The Index can be a combination of static and dynamic values consisting of field paths followed by `\|\|` followed by another field path or a static value.
732740
733-
A dynamic value is encased in single curly brackets `{}` and MUST end with a static fallback value separated with `||`.
741+
A dynamic value is encased in single curly brackets `{}` and MUST end with a static fallback value separated with `\|\|`.
734742
735743
Static values can only contain alphanumeric characters along with dashes, underscores, dots and forward slashes.
736744
737-
When forwarding logs to the Red Hat Managed Elasticsearch, the index must match the pattern ^(app|infra|audit)-write$
745+
When forwarding logs to the Red Hat Managed Elasticsearch, the index must match the pattern ^(app\|infra\|audit)-write$
738746
where the prefix depends upon the log_type. This requires defining a distinct output for each log type or distinct pipelines
739747
with the openshiftLabels filter. See the product documentation for examples.
740748
741749
Example:
742750
743-
1. foo-{.bar||"none"}
751+
1. foo-{.bar\|\|"none"}
744752
745-
2. {.foo||.bar||"missing"}
753+
2. {.foo\|\|.bar\|\|"missing"}
746754
747-
3. foo.{.bar.baz||.qux.quux.corge||.grault||"nil"}-waldo.fred{.plugh||"none"}
755+
3. foo.{.bar.baz\|\|.qux.quux.corge\|\|.grault\|\|"nil"}-waldo.fred{.plugh\|\|"none"}
748756
displayName: Log Index
749757
path: outputs[0].elasticsearch.index
750758
x-descriptors:
@@ -1460,6 +1468,193 @@ spec:
14601468
path: outputs[0].rateLimit.maxRecordsPerSecond
14611469
x-descriptors:
14621470
- urn:alm:descriptor:com.tectonic.ui:number
1471+
- description: S3 configures forwarding log events to Amazon S3 buckets
1472+
displayName: Amazon S3
1473+
path: outputs[0].s3
1474+
- description: Authentication sets credentials for authenticating the requests.
1475+
displayName: Authentication Options
1476+
path: outputs[0].s3.authentication
1477+
- description: |-
1478+
AssumeRole specifies an additional AWS role to assume for forwarding logs.
1479+
This enables cross-account log forwarding by using the initial role to authenticate,
1480+
then assume a role in order to access cross-account services.
1481+
displayName: Assume Role
1482+
path: outputs[0].s3.authentication.assumeRole
1483+
- description: |-
1484+
ExternalID is the external ID to match when assuming the role.
1485+
This is optional and can be used as an additional security measure to ensure that only the intended
1486+
entity can assume the role.
1487+
1488+
The ExternalId must be a minimum of 2 characters and a maximum of 1,224 characters.
1489+
The value must be alphanumeric without whitespace and can also include the following symbols:
1490+
plus(+), equal(=), comma(,), period(.), at(@), colon(:), forward slash(/), and hyphen(-).
1491+
displayName: External ID
1492+
path: outputs[0].s3.authentication.assumeRole.externalID
1493+
- description: RoleARN points to the secret containing the ARN of the role to
1494+
assume for cross-account access.
1495+
displayName: Assume Role ARN Secret
1496+
path: outputs[0].s3.authentication.assumeRole.roleARN
1497+
- description: Key contains the name of the key inside the referenced Secret.
1498+
displayName: Key Name
1499+
path: outputs[0].s3.authentication.assumeRole.roleARN.key
1500+
x-descriptors:
1501+
- urn:alm:descriptor:com.tectonic.ui:text
1502+
- description: SecretName contains the name of the Secret containing the referenced
1503+
value.
1504+
displayName: Secret Name
1505+
path: outputs[0].s3.authentication.assumeRole.roleARN.secretName
1506+
x-descriptors:
1507+
- urn:alm:descriptor:com.tectonic.ui:text
1508+
- description: |-
1509+
SessionName is an optional identifier for the assumed role session.
1510+
If not provided, a default session name will be generated.
1511+
displayName: Session Name
1512+
path: outputs[0].s3.authentication.assumeRole.sessionName
1513+
x-descriptors:
1514+
- urn:alm:descriptor:com.tectonic.ui:text
1515+
- description: AwsAccessKey points to the AWS access key id and secret to be
1516+
used for authentication.
1517+
displayName: Access Key
1518+
path: outputs[0].s3.authentication.awsAccessKey
1519+
- description: KeyId points to the AWS access key id to be used for authentication.
1520+
displayName: Secret with Access Key ID
1521+
path: outputs[0].s3.authentication.awsAccessKey.keyId
1522+
- description: Key contains the name of the key inside the referenced Secret.
1523+
displayName: Key Name
1524+
path: outputs[0].s3.authentication.awsAccessKey.keyId.key
1525+
x-descriptors:
1526+
- urn:alm:descriptor:com.tectonic.ui:text
1527+
- description: SecretName contains the name of the Secret containing the referenced
1528+
value.
1529+
displayName: Secret Name
1530+
path: outputs[0].s3.authentication.awsAccessKey.keyId.secretName
1531+
x-descriptors:
1532+
- urn:alm:descriptor:com.tectonic.ui:text
1533+
- description: KeySecret points to the AWS access key secret to be used for
1534+
authentication.
1535+
displayName: Secret with Access Key Secret
1536+
path: outputs[0].s3.authentication.awsAccessKey.keySecret
1537+
- description: Key contains the name of the key inside the referenced Secret.
1538+
displayName: Key Name
1539+
path: outputs[0].s3.authentication.awsAccessKey.keySecret.key
1540+
x-descriptors:
1541+
- urn:alm:descriptor:com.tectonic.ui:text
1542+
- description: SecretName contains the name of the Secret containing the referenced
1543+
value.
1544+
displayName: Secret Name
1545+
path: outputs[0].s3.authentication.awsAccessKey.keySecret.secretName
1546+
x-descriptors:
1547+
- urn:alm:descriptor:com.tectonic.ui:text
1548+
- description: |-
1549+
IamRole points to the secret containing the role ARN to be used for authentication.
1550+
This can be used for authentication in STS-enabled clusters when additionally specifying
1551+
a web identity token
1552+
displayName: Amazon IAM Role
1553+
path: outputs[0].s3.authentication.iamRole
1554+
- description: |-
1555+
RoleARN specifies the secret containing the role ARN to be used for AWS authentication.
1556+
This role requires an OIDC provider to be configured in an STS-enabled cluster.
1557+
displayName: RoleARN Secret
1558+
path: outputs[0].s3.authentication.iamRole.roleARN
1559+
- description: Key contains the name of the key inside the referenced Secret.
1560+
displayName: Key Name
1561+
path: outputs[0].s3.authentication.iamRole.roleARN.key
1562+
x-descriptors:
1563+
- urn:alm:descriptor:com.tectonic.ui:text
1564+
- description: SecretName contains the name of the Secret containing the referenced
1565+
value.
1566+
displayName: Secret Name
1567+
path: outputs[0].s3.authentication.iamRole.roleARN.secretName
1568+
x-descriptors:
1569+
- urn:alm:descriptor:com.tectonic.ui:text
1570+
- description: Token specifies a bearer token to be used for authenticating
1571+
requests.
1572+
displayName: Token
1573+
path: outputs[0].s3.authentication.iamRole.token
1574+
- description: From is the source from where to find the token
1575+
displayName: Token Source
1576+
path: outputs[0].s3.authentication.iamRole.token.from
1577+
- description: Use Secret if the value should be sourced from a Secret in the
1578+
same namespace.
1579+
displayName: Token Secret
1580+
path: outputs[0].s3.authentication.iamRole.token.secret
1581+
- description: Name of the key used to get the value from the referenced Secret.
1582+
displayName: Key Name
1583+
path: outputs[0].s3.authentication.iamRole.token.secret.key
1584+
x-descriptors:
1585+
- urn:alm:descriptor:com.tectonic.ui:text
1586+
- description: Name of secret
1587+
displayName: Secret Name
1588+
path: outputs[0].s3.authentication.iamRole.token.secret.name
1589+
x-descriptors:
1590+
- urn:alm:descriptor:com.tectonic.ui:text
1591+
- description: Type is the type of cloudwatch authentication to configure
1592+
displayName: Authentication Type
1593+
path: outputs[0].s3.authentication.type
1594+
- description: |-
1595+
Bucket specifies the S3 bucket name where logs will be stored.
1596+
1597+
String name absent leading `s3://` or trailing `/` and truncated to 63 characters to meet length restrictions
1598+
displayName: S3 Bucket Name
1599+
path: outputs[0].s3.bucket
1600+
x-descriptors:
1601+
- urn:alm:descriptor:com.tectonic.ui:text
1602+
- description: |-
1603+
KeyPrefix is a templated string that defines the S3 key prefix for log objects. It is a combination of
1604+
static or dynamic values consisting of field paths separated by `\|\|` and ending with a static
1605+
fallback value (e.g. logs_{.kubernetes.namespace_name\|\|.hostname\|\|"unknown"}_my_workload_{.openshift.sequence_id\|\|"none"}).
1606+
1607+
Prefixes are necessary for partitioning logs from other objects in the bucket. If the prefix represents a
1608+
directory, it must end in `/` to act as a directory path. A trailing `/` (forward slash) is not automatically added.
1609+
1610+
Dynamic values are encased in single curly brackets `{}` and MUST end with a static fallback value separated
1611+
with `\|\|`. Static values can only contain alphanumeric characters along with dashes, underscores, dots and forward slashes.
1612+
1613+
Examples:
1614+
1615+
1. logs_{.kubernetes.namespace_name\|\|"none"}/
1616+
1617+
2. {.log_type\|\|.log_source\|\|"missing"}/
1618+
1619+
3. my_workload.{.hostname\|\|.qux.quux.corge\|\|.grault\|\|"nil"}-waldo.fred{.plugh\|\|"none"}/
1620+
displayName: Key Prefix
1621+
path: outputs[0].s3.keyPrefix
1622+
x-descriptors:
1623+
- urn:alm:descriptor:com.tectonic.ui:text
1624+
- displayName: Amazon Region
1625+
path: outputs[0].s3.region
1626+
x-descriptors:
1627+
- urn:alm:descriptor:com.tectonic.ui:text
1628+
- description: Tuning specs tuning for the output
1629+
displayName: Tuning Options
1630+
path: outputs[0].s3.tuning
1631+
- description: |-
1632+
Compression causes data to be compressed before sending over the network.
1633+
It is an error if the compression type is not supported by the output.
1634+
displayName: Compression
1635+
path: outputs[0].s3.tuning.compression
1636+
- displayName: Delivery Mode
1637+
path: outputs[0].s3.tuning.deliveryMode
1638+
- description: MaxRetryDuration is the maximum time to wait between retry attempts
1639+
after a delivery failure.
1640+
displayName: Maximum Retry Duration
1641+
path: outputs[0].s3.tuning.maxRetryDuration
1642+
- description: MaxWrite limits the maximum payload in terms of bytes of a single
1643+
"send" to the output.
1644+
displayName: Batch Size
1645+
path: outputs[0].s3.tuning.maxWrite
1646+
- description: MinRetryDuration is the minimum time to wait between attempts
1647+
to retry after delivery a failure.
1648+
displayName: Minimum Retry Duration
1649+
path: outputs[0].s3.tuning.minRetryDuration
1650+
- description: |-
1651+
URL is the custom S3-compatible endpoint URL.
1652+
If not specified, the default AWS S3 endpoint will be used.
1653+
This is useful for S3-compatible services like MinIO, Ceph Object Gateway, or Dell EMC ECS.
1654+
displayName: Custom Endpoint URL
1655+
path: outputs[0].s3.url
1656+
x-descriptors:
1657+
- urn:alm:descriptor:com.tectonic.ui:text
14631658
- description: Splunk configures forwarding log events to Splunk's HTTP event
14641659
collector
14651660
displayName: Splunk

internal/network/ports.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,13 @@ func getPortProtocolFromOutputURL(output obs.OutputSpec) []factory.PortProtocol
8080
urlStr = output.HTTP.URL
8181
}
8282
case obs.OutputTypeCloudwatch:
83-
if output.Cloudwatch != nil && output.Cloudwatch.URL != "" {
83+
if output.Cloudwatch != nil {
8484
urlStr = output.Cloudwatch.URL
8585
}
86+
case obs.OutputTypeS3:
87+
if output.S3 != nil {
88+
urlStr = output.S3.URL
89+
}
8690
case obs.OutputTypeKafka:
8791
// For kafka, prefer the URL over the broker URLs
8892
if output.Kafka != nil {
@@ -180,7 +184,7 @@ func getDefaultPort(outputType obs.OutputType, urlStr string) int32 {
180184
return 4318
181185
case obs.OutputTypeLokiStack: // LokiStack uses 8080
182186
return 8080
183-
case obs.OutputTypeCloudwatch, obs.OutputTypeAzureMonitor, obs.OutputTypeGoogleCloudLogging:
187+
case obs.OutputTypeCloudwatch, obs.OutputTypeAzureMonitor, obs.OutputTypeGoogleCloudLogging, obs.OutputTypeS3:
184188
return 443
185189
case obs.OutputTypeKafka:
186190
// Kafka uses 9092 for plaintext (tcp), 9093 for TLS

internal/network/ports_test.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ var _ = Describe("Network Ports", func() {
4848
Entry("should return 443 for AzureMonitor", obs.OutputTypeAzureMonitor, "", int32(443)),
4949
Entry("should return 443 for GoogleCloudLogging", obs.OutputTypeGoogleCloudLogging, "", int32(443)),
5050
Entry("should return 8080 for LokiStack", obs.OutputTypeLokiStack, "", int32(8080)),
51+
Entry("should return 443 for S3", obs.OutputTypeS3, "", int32(443)),
5152

5253
// Kafka with different schemes
5354
Entry("should return 9092 for plaintext Kafka", obs.OutputTypeKafka, "tcp://kafka.example.com", int32(9092)),
@@ -60,6 +61,12 @@ var _ = Describe("Network Ports", func() {
6061
Entry("should return 443 for HTTP with no scheme", obs.OutputTypeHTTP, "", int32(443)),
6162
)
6263

64+
It("should not panic for all supported output types", func() {
65+
for _, outputType := range obs.OutputTypes {
66+
Expect(func() { getDefaultPort(outputType, "") }).ToNot(Panic())
67+
}
68+
})
69+
6370
It("should panic for unknown output type", func() {
6471
Expect(func() { getDefaultPort(obs.OutputType("unknown"), "") }).To(Panic())
6572
})
@@ -245,6 +252,25 @@ var _ = Describe("Network Ports", func() {
245252
),
246253
)
247254

255+
DescribeTable("S3",
256+
func(urlStr string, expected []factory.PortProtocol) {
257+
output := obs.OutputSpec{
258+
Type: obs.OutputTypeS3,
259+
S3: &obs.S3{URL: urlStr},
260+
}
261+
ports := getPortProtocolFromOutputURL(output)
262+
Expect(ports).To(Equal(expected))
263+
},
264+
Entry("should extract port from S3 URL",
265+
"https://some-s3-bucket.com:5555",
266+
[]factory.PortProtocol{{Port: 5555, Protocol: corev1.ProtocolTCP}},
267+
),
268+
Entry("should use default port for S3 without explicit port",
269+
"https://s3.amazonaws.com",
270+
[]factory.PortProtocol{{Port: 443, Protocol: corev1.ProtocolTCP}},
271+
),
272+
)
273+
248274
DescribeTable("Kafka",
249275
func(kafka *obs.Kafka, expectedPorts []factory.PortProtocol) {
250276
output := obs.OutputSpec{

0 commit comments

Comments
 (0)