mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Alerting: Add TLS, QoS and retain options to the MQTT receiver (#92331)
This commit is contained in:
parent
b52e6ba552
commit
e59ea00518
1
.github/CODEOWNERS
vendored
1
.github/CODEOWNERS
vendored
@ -199,6 +199,7 @@
|
||||
/devenv/docker/blocks/mariadb/ @grafana/oss-big-tent
|
||||
/devenv/docker/blocks/memcached/ @grafana/grafana-backend-group
|
||||
/devenv/docker/blocks/mimir_backend/ @grafana/alerting-backend
|
||||
/devenv/docker/blocks/mqtt/ @grafana/alerting-backend
|
||||
/devenv/docker/blocks/mssql/ @grafana/partner-datasources
|
||||
/devenv/docker/blocks/mssql_arm64/ @grafana/partner-datasources
|
||||
/devenv/docker/blocks/mssql_tests/ @grafana/partner-datasources
|
||||
|
31
devenv/docker/blocks/mqtt/README.md
Normal file
31
devenv/docker/blocks/mqtt/README.md
Normal file
@ -0,0 +1,31 @@
|
||||
# NanoMQ MQTT broker
|
||||
|
||||
Starts a [NanoMQ MQTT broker](https://nanomq.io/docs/en/latest/).
|
||||
|
||||
## Authentication
|
||||
|
||||
The broker is configured to use a simple username/password authentication.
|
||||
See [./nanomq_pwd.conf](./nanomq_pwd.conf) for the default credentials.
|
||||
|
||||
## TLS Certificates
|
||||
|
||||
If you want to configure an MQTT contact point in Grafana Alerting with TLS, you need to provide a certificate and key.
|
||||
|
||||
You can find them in `/etc/certs` directory in the container:
|
||||
|
||||
``` shell
|
||||
docker exec devenv-mqtt-1 ls /etc/certs/
|
||||
```
|
||||
|
||||
### CA Certificate
|
||||
|
||||
``` shell
|
||||
docker exec devenv-mqtt-1 cat /etc/certs/ca.pem
|
||||
```
|
||||
|
||||
### Client certificates
|
||||
|
||||
``` shell
|
||||
docker exec devenv-mqtt-1 cat /etc/certs/client.pem
|
||||
docker exec devenv-mqtt-1 cat /etc/certs/client.key
|
||||
```
|
9
devenv/docker/blocks/mqtt/build/Dockerfile
Normal file
9
devenv/docker/blocks/mqtt/build/Dockerfile
Normal file
@ -0,0 +1,9 @@
|
||||
FROM emqx/nanomq:0.21.11-full
|
||||
|
||||
RUN apt-get update && apt-get install -y \
|
||||
openssl \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY ./san.cnf /etc/certs/san.cnf
|
||||
COPY ./gen_certs.sh /etc/certs/gen_certs.sh
|
||||
RUN /etc/certs/gen_certs.sh
|
18
devenv/docker/blocks/mqtt/build/gen_certs.sh
Executable file
18
devenv/docker/blocks/mqtt/build/gen_certs.sh
Executable file
@ -0,0 +1,18 @@
|
||||
#!/bin/bash
|
||||
|
||||
DAYS_VALID=3650
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
# Create CA certificate
|
||||
openssl genpkey -algorithm RSA -out "$SCRIPT_DIR/ca.key"
|
||||
openssl req -new -x509 -days $DAYS_VALID -key "$SCRIPT_DIR/ca.key" -out "$SCRIPT_DIR/ca.pem" -subj "/CN=My CA"
|
||||
|
||||
# Create server certificate
|
||||
openssl genpkey -algorithm RSA -out "$SCRIPT_DIR/server.key"
|
||||
openssl req -new -key "$SCRIPT_DIR/server.key" -out "$SCRIPT_DIR/server.csr" -subj "/CN=localhost"
|
||||
openssl x509 -req -days $DAYS_VALID -in "$SCRIPT_DIR/server.csr" -CA "$SCRIPT_DIR/ca.pem" -CAkey "$SCRIPT_DIR/ca.key" -CAcreateserial -out "$SCRIPT_DIR/server.pem" -extfile "$SCRIPT_DIR/san.cnf" -extensions v3_req
|
||||
|
||||
# Create client key and certificate
|
||||
openssl genpkey -algorithm RSA -out "$SCRIPT_DIR/client.key"
|
||||
openssl req -new -key "$SCRIPT_DIR/client.key" -out "$SCRIPT_DIR/client.csr" -subj "/CN=Client"
|
||||
openssl x509 -req -days $DAYS_VALID -in "$SCRIPT_DIR/client.csr" -CA "$SCRIPT_DIR/ca.pem" -CAkey "$SCRIPT_DIR/ca.key" -CAcreateserial -out "$SCRIPT_DIR/client.pem" -extfile "$SCRIPT_DIR/san.cnf" -extensions v3_req
|
7
devenv/docker/blocks/mqtt/build/san.cnf
Normal file
7
devenv/docker/blocks/mqtt/build/san.cnf
Normal file
@ -0,0 +1,7 @@
|
||||
[ v3_req ]
|
||||
subjectAltName = @alt_names
|
||||
|
||||
[ alt_names ]
|
||||
DNS.1 = localhost
|
||||
IP.1 = 127.0.0.1
|
||||
IP.2 = ::1
|
12
devenv/docker/blocks/mqtt/docker-compose.yaml
Normal file
12
devenv/docker/blocks/mqtt/docker-compose.yaml
Normal file
@ -0,0 +1,12 @@
|
||||
mqtt:
|
||||
build:
|
||||
context: docker/blocks/mqtt/build
|
||||
ports:
|
||||
- "127.0.0.1:1883:1883" # MQTT
|
||||
- "127.0.0.1:8883:8883" # MQTT over TLS
|
||||
- "127.0.0.1:8083:8083" # MQTT over WS
|
||||
- "127.0.0.1:8443:8443" # MQTT over WSS
|
||||
volumes:
|
||||
- ${PWD}/docker/blocks/mqtt/nanomq.conf:/etc/nanomq.conf
|
||||
- ${PWD}/docker/blocks/mqtt/nanomq_pwd.conf:/etc/nanomq_pwd.conf
|
||||
- ${PWD}/docker/blocks/mqtt/nanomq_acl.conf:/etc/nanomq_acl.conf
|
40
devenv/docker/blocks/mqtt/nanomq.conf
Normal file
40
devenv/docker/blocks/mqtt/nanomq.conf
Normal file
@ -0,0 +1,40 @@
|
||||
log {
|
||||
to=console
|
||||
level=info
|
||||
}
|
||||
|
||||
listeners.tcp {
|
||||
bind = "0.0.0.0:1883"
|
||||
}
|
||||
|
||||
|
||||
listeners.ssl {
|
||||
bind = "0.0.0.0:8883"
|
||||
|
||||
keyfile = "/etc/certs/server.key"
|
||||
certfile = "/etc/certs/server.pem"
|
||||
cacertfile = "/etc/certs/ca.pem"
|
||||
|
||||
# Change these settings to true if you want to deny
|
||||
# access for clients that don't have a certificate.
|
||||
verify_peer = false
|
||||
fail_if_no_peer_cert = false
|
||||
}
|
||||
|
||||
listeners.ws {
|
||||
bind = "0.0.0.0:8083"
|
||||
}
|
||||
|
||||
listeners.wss {
|
||||
bind = "0.0.0.0:8443"
|
||||
}
|
||||
|
||||
auth {
|
||||
allow_anonymous = false
|
||||
no_match = deny
|
||||
deny_action = disconnect
|
||||
password = {include "/etc/nanomq_pwd.conf"}
|
||||
acl = {
|
||||
include "/etc/nanomq_acl.conf"
|
||||
}
|
||||
}
|
7
devenv/docker/blocks/mqtt/nanomq_acl.conf
Normal file
7
devenv/docker/blocks/mqtt/nanomq_acl.conf
Normal file
@ -0,0 +1,7 @@
|
||||
rules = [
|
||||
{"permit": "allow", "username": "grafana", "action": "subscribe", "topics": ["#"]}
|
||||
{"permit": "allow", "username": "grafana", "action": "publish", "topics": ["#"]}
|
||||
{"permit": "allow", "username": "admin", "action": "subscribe", "topics": ["#"]}
|
||||
{"permit": "allow", "username": "admin", "action": "publish", "topics": ["#"]}
|
||||
{"permit": "deny"}
|
||||
]
|
2
devenv/docker/blocks/mqtt/nanomq_pwd.conf
Normal file
2
devenv/docker/blocks/mqtt/nanomq_pwd.conf
Normal file
@ -0,0 +1,2 @@
|
||||
admin:admin
|
||||
grafana:grafana
|
@ -506,15 +506,26 @@ The following sections detail the supported settings and secure settings for eac
|
||||
|
||||
#### Alert notification `MQTT`
|
||||
|
||||
| Name | Secure setting |
|
||||
| ------------- | -------------- |
|
||||
| brokerUrl | |
|
||||
| clientId | |
|
||||
| topic | |
|
||||
| messageFormat | |
|
||||
| username | |
|
||||
| password | yes |
|
||||
| retain | |
|
||||
| qos | |
|
||||
| tlsConfig | |
|
||||
|
||||
##### TLS config
|
||||
|
||||
| Name | Secure setting |
|
||||
| ------------------ | -------------- |
|
||||
| brokerUrl | |
|
||||
| clientId | |
|
||||
| topic | |
|
||||
| messageFormat |
|
||||
| username | |
|
||||
| password | yes |
|
||||
| insecureSkipVerify | |
|
||||
| clientCertificate | yes |
|
||||
| clientKey | yes |
|
||||
| caCertificate | yes |
|
||||
|
||||
#### Alert notification `pagerduty`
|
||||
|
||||
|
@ -362,8 +362,20 @@ settings:
|
||||
username: grafana
|
||||
# <string>
|
||||
password: password1
|
||||
# <string>
|
||||
qos: 0
|
||||
# <bool>
|
||||
insecureSkipVerify: false
|
||||
retain: false
|
||||
# <map>
|
||||
tlsConfig:
|
||||
# <bool>
|
||||
insecureSkipVerify: false
|
||||
# <string>
|
||||
clientCertificate: certificate in PEM format
|
||||
# <string>
|
||||
clientKey: key in PEM format
|
||||
# <string>
|
||||
caCertificate: CA certificate in PEM format
|
||||
```
|
||||
|
||||
{{< /collapse >}}
|
||||
|
6
go.mod
6
go.mod
@ -73,9 +73,9 @@ require (
|
||||
github.com/googleapis/gax-go/v2 v2.13.0 // @grafana/grafana-backend-group
|
||||
github.com/gorilla/mux v1.8.1 // @grafana/grafana-backend-group
|
||||
github.com/gorilla/websocket v1.5.0 // @grafana/grafana-app-platform-squad
|
||||
github.com/grafana/alerting v0.0.0-20240829185616-8454ac21d7e5 // @grafana/alerting-backend
|
||||
github.com/grafana/authlib v0.0.0-20240906122029-0100695765b9 // @grafana/identity-access-team
|
||||
github.com/grafana/authlib/claims v0.0.0-20240903121118-16441568af1e // @grafana/identity-access-team
|
||||
github.com/grafana/alerting v0.0.0-20240917171353-6c25eb6eff10 // @grafana/alerting-backend
|
||||
github.com/grafana/authlib v0.0.0-20240827201526-24af227df935 // @grafana/identity-access-team
|
||||
github.com/grafana/authlib/claims v0.0.0-20240827210201-19d5347dd8dd // @grafana/identity-access-team
|
||||
github.com/grafana/codejen v0.0.3 // @grafana/dataviz-squad
|
||||
github.com/grafana/cuetsy v0.1.11 // @grafana/grafana-as-code
|
||||
github.com/grafana/dataplane/examples v0.0.1 // @grafana/observability-metrics
|
||||
|
12
go.sum
12
go.sum
@ -2255,12 +2255,12 @@ github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
||||
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/grafana/alerting v0.0.0-20240829185616-8454ac21d7e5 h1:gQprHfu5/GT/mpPuRm3QVL+7+0j1QsvKJuPIzQAsezM=
|
||||
github.com/grafana/alerting v0.0.0-20240829185616-8454ac21d7e5/go.mod h1:GMLi6d09Xqo96fCVUjNk//rcjP5NKEdjOzfWIffD5r4=
|
||||
github.com/grafana/authlib v0.0.0-20240906122029-0100695765b9 h1:e+kFqd2sECBhbxOV1NoVxsudLygNQuu9bO+7FjNTkXo=
|
||||
github.com/grafana/authlib v0.0.0-20240906122029-0100695765b9/go.mod h1:PFzXbCrn0GIpN4KwT6NP1l5Z1CPLfmKHnYx8rZzQcyY=
|
||||
github.com/grafana/authlib/claims v0.0.0-20240903121118-16441568af1e h1:ng5SopWamGS0MHaCj2e5huWYxAfMeCrj1l/dbJnfiow=
|
||||
github.com/grafana/authlib/claims v0.0.0-20240903121118-16441568af1e/go.mod h1:r+F8H6awwjNQt/KPZ2GNwjk8TvsJ7/gxzkXN26GlL/A=
|
||||
github.com/grafana/alerting v0.0.0-20240917171353-6c25eb6eff10 h1:oDbLKM34O+JUF9EQFS+9aYhdYoeNfUpXqNjFCLIxwF4=
|
||||
github.com/grafana/alerting v0.0.0-20240917171353-6c25eb6eff10/go.mod h1:GMLi6d09Xqo96fCVUjNk//rcjP5NKEdjOzfWIffD5r4=
|
||||
github.com/grafana/authlib v0.0.0-20240827201526-24af227df935 h1:nT4UY61s2flsiLkU2jDqtqFhOLwqh355+8ZhnavKoMQ=
|
||||
github.com/grafana/authlib v0.0.0-20240827201526-24af227df935/go.mod h1:ER7bMzNNWTN/5Zl3pwqfgS6XEhcanjrvL7lOp8Ow6oc=
|
||||
github.com/grafana/authlib/claims v0.0.0-20240827210201-19d5347dd8dd h1:sIlR7n38/MnZvX2qxDEszywXdI5soCwQ78aTDSARvus=
|
||||
github.com/grafana/authlib/claims v0.0.0-20240827210201-19d5347dd8dd/go.mod h1:r+F8H6awwjNQt/KPZ2GNwjk8TvsJ7/gxzkXN26GlL/A=
|
||||
github.com/grafana/codejen v0.0.3 h1:tAWxoTUuhgmEqxJPOLtJoxlPBbMULFwKFOcRsPRPXDw=
|
||||
github.com/grafana/codejen v0.0.3/go.mod h1:zmwwM/DRyQB7pfuBjTWII3CWtxcXh8LTwAYGfDfpR6s=
|
||||
github.com/grafana/cue v0.0.0-20230926092038-971951014e3f h1:TmYAMnqg3d5KYEAaT6PtTguL2GjLfvr6wnAX8Azw6tQ=
|
||||
|
@ -559,12 +559,14 @@ github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl
|
||||
github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4=
|
||||
github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q=
|
||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||
github.com/grafana/authlib/claims v0.0.0-20240827210201-19d5347dd8dd/go.mod h1:r+F8H6awwjNQt/KPZ2GNwjk8TvsJ7/gxzkXN26GlL/A=
|
||||
github.com/grafana/alerting v0.0.0-20240830172655-aa466962ea18 h1:3cQ+d+fkNL2EqpARaBVG34KlVz7flDujYfDx3njvdh8=
|
||||
github.com/grafana/alerting v0.0.0-20240830172655-aa466962ea18/go.mod h1:GMLi6d09Xqo96fCVUjNk//rcjP5NKEdjOzfWIffD5r4=
|
||||
github.com/grafana/gomemcache v0.0.0-20240229205252-cd6a66d6fb56/go.mod h1:PGk3RjYHpxMM8HFPhKKo+vve3DdlPUELZLSDEFehPuU=
|
||||
github.com/grafana/pyroscope-go/godeltaprof v0.1.6/go.mod h1:Tk376Nbldo4Cha9RgiU7ik8WKFkNpfds98aUzS8omLE=
|
||||
github.com/grafana/thema v0.0.0-20230511182720-3146087fcc26 h1:HX927q4X1n451pnGb8U0wq74i8PCzuxVjzv7TyD10kc=
|
||||
github.com/grafana/thema v0.0.0-20230511182720-3146087fcc26/go.mod h1:Pn9nfzCk7nV0mvNgwusgCjCROZP6nm4GpwTnmEhLT24=
|
||||
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k=
|
||||
github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 h1:MJG/KsmcqMwFAkh8mTnAwhyKoB+sTAnY4CACC110tbU=
|
||||
github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645/go.mod h1:6iZfnjpejD4L/4DwD7NryNaJyCQdzwWwH2MWhCA90Kw=
|
||||
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8=
|
||||
|
@ -401,6 +401,12 @@ func (c contactPointsExtension) UpdateStructDescriptor(structDescriptor *jsonite
|
||||
desc.Decoder = codec
|
||||
desc.Encoder = codec
|
||||
}
|
||||
if structDescriptor.Type == reflect2.TypeOf(definitions.MqttIntegration{}) {
|
||||
codec := &numberAsStringCodec{ignoreError: true}
|
||||
desc := structDescriptor.GetField("QoS")
|
||||
desc.Decoder = codec
|
||||
desc.Encoder = codec
|
||||
}
|
||||
}
|
||||
|
||||
type emailAddressCodec struct{}
|
||||
|
@ -184,4 +184,30 @@ func TestContactPointFromContactPointExports(t *testing.T) {
|
||||
require.Nil(t, result.OnCall[1].MaxAlerts)
|
||||
require.Nil(t, result.OnCall[2].MaxAlerts)
|
||||
})
|
||||
|
||||
t.Run("mqtt with optional numbers as string", func(t *testing.T) {
|
||||
export := definitions.ContactPointExport{
|
||||
Name: "test",
|
||||
Receivers: []definitions.ReceiverExport{
|
||||
{
|
||||
Type: "mqtt",
|
||||
Settings: definitions.RawMessage(`{ "qos" : "112" }`),
|
||||
},
|
||||
{
|
||||
Type: "mqtt",
|
||||
Settings: definitions.RawMessage(`{ "qos" : "test" }`),
|
||||
},
|
||||
{
|
||||
Type: "mqtt",
|
||||
Settings: definitions.RawMessage(`{ "qos" : null }`),
|
||||
},
|
||||
},
|
||||
}
|
||||
result, err := ContactPointFromContactPointExport(export)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, result.Mqtt, 3)
|
||||
require.Equal(t, int64(112), *result.Mqtt[0].QoS)
|
||||
require.Nil(t, result.Mqtt[1].QoS)
|
||||
require.Nil(t, result.Mqtt[2].QoS)
|
||||
})
|
||||
}
|
||||
|
@ -85,17 +85,26 @@ type LineIntegration struct {
|
||||
Description *string `json:"description,omitempty" yaml:"description,omitempty" hcl:"description"`
|
||||
}
|
||||
|
||||
type TLSConfig struct {
|
||||
InsecureSkipVerify *bool `json:"insecureSkipVerify,omitempty" yaml:"insecureSkipVerify,omitempty" hcl:"insecure_skip_verify"`
|
||||
TLSCACertificate *Secret `json:"caCertificate,omitempty" yaml:"caCertificate,omitempty" hcl:"ca_certificate"`
|
||||
TLSClientCertificate *Secret `json:"clientCertificate,omitempty" yaml:"clientCertificate,omitempty" hcl:"client_certificate"`
|
||||
TLSClientKey *Secret `json:"clientKey,omitempty" yaml:"clientKey,omitempty" hcl:"client_key"`
|
||||
}
|
||||
|
||||
type MqttIntegration struct {
|
||||
DisableResolveMessage *bool `json:"-" yaml:"-" hcl:"disable_resolve_message"`
|
||||
|
||||
BrokerURL *string `json:"brokerUrl,omitempty" yaml:"brokerUrl,omitempty" hcl:"broker_url"`
|
||||
ClientID *string `json:"clientId,omitempty" yaml:"clientId,omitempty" hcl:"client_id"`
|
||||
Topic *string `json:"topic,omitempty" yaml:"topic,omitempty" hcl:"topic"`
|
||||
Message *string `json:"message,omitempty" yaml:"message,omitempty" hcl:"message"`
|
||||
MessageFormat *string `json:"messageFormat,omitempty" yaml:"messageFormat,omitempty" hcl:"message_format"`
|
||||
Username *string `json:"username,omitempty" yaml:"username,omitempty" hcl:"username"`
|
||||
Password *Secret `json:"password,omitempty" yaml:"password,omitempty" hcl:"password"`
|
||||
InsecureSkipVerify *bool `json:"insecureSkipVerify,omitempty" yaml:"insecureSkipVerify,omitempty" hcl:"insecure_skip_verify"`
|
||||
BrokerURL *string `json:"brokerUrl,omitempty" yaml:"brokerUrl,omitempty" hcl:"broker_url"`
|
||||
ClientID *string `json:"clientId,omitempty" yaml:"clientId,omitempty" hcl:"client_id"`
|
||||
Topic *string `json:"topic,omitempty" yaml:"topic,omitempty" hcl:"topic"`
|
||||
Message *string `json:"message,omitempty" yaml:"message,omitempty" hcl:"message"`
|
||||
MessageFormat *string `json:"messageFormat,omitempty" yaml:"messageFormat,omitempty" hcl:"message_format"`
|
||||
Username *string `json:"username,omitempty" yaml:"username,omitempty" hcl:"username"`
|
||||
Password *Secret `json:"password,omitempty" yaml:"password,omitempty" hcl:"password"`
|
||||
QoS *int64 `json:"qos,omitempty" yaml:"qos,omitempty" hcl:"qos"`
|
||||
Retain *bool `json:"retain,omitempty" yaml:"retain,omitempty" hcl:"retain"`
|
||||
TLSConfig *TLSConfig `json:"tlsConfig,omitempty" yaml:"tlsConfig,omitempty" hcl:"tls_config,block"`
|
||||
}
|
||||
|
||||
type OnCallIntegration struct {
|
||||
|
@ -1325,12 +1325,75 @@ func GetAvailableNotifiers() []*NotifierPlugin {
|
||||
Secure: true,
|
||||
},
|
||||
{
|
||||
Label: "Disable certificate verification",
|
||||
Element: ElementTypeCheckbox,
|
||||
Description: "Do not verify the broker's certificate chain and host name.",
|
||||
PropertyName: "insecureSkipVerify",
|
||||
Label: "QoS",
|
||||
Element: ElementTypeSelect,
|
||||
SelectOptions: []SelectOption{
|
||||
{
|
||||
Value: "0",
|
||||
Label: "At most once (0)",
|
||||
},
|
||||
{
|
||||
Value: "1",
|
||||
Label: "At least once (1)",
|
||||
},
|
||||
{
|
||||
Value: "2",
|
||||
Label: "Exactly once (2)",
|
||||
},
|
||||
},
|
||||
Description: "The quality of service to use when sending the message.",
|
||||
PropertyName: "qos",
|
||||
Required: false,
|
||||
},
|
||||
{
|
||||
Label: "Retain",
|
||||
Description: "If set to true, the message will be retained by the broker.",
|
||||
Element: ElementTypeCheckbox,
|
||||
PropertyName: "retain",
|
||||
Required: false,
|
||||
},
|
||||
{
|
||||
Label: "TLS",
|
||||
PropertyName: "tlsConfig",
|
||||
Description: "TLS configuration options",
|
||||
Element: ElementTypeSubform,
|
||||
SubformOptions: []NotifierOption{
|
||||
{
|
||||
Label: "Disable certificate verification",
|
||||
Element: ElementTypeCheckbox,
|
||||
Description: "Do not verify the broker's certificate chain and host name.",
|
||||
PropertyName: "insecureSkipVerify",
|
||||
Required: false,
|
||||
},
|
||||
{
|
||||
Label: "CA Certificate",
|
||||
Element: ElementTypeTextArea,
|
||||
Description: "Certificate in PEM format to use when verifying the broker's certificate chain.",
|
||||
InputType: InputTypeText,
|
||||
PropertyName: "caCertificate",
|
||||
Required: false,
|
||||
Secure: true,
|
||||
},
|
||||
{
|
||||
Label: "Client Certificate",
|
||||
Element: ElementTypeTextArea,
|
||||
Description: "Client certificate in PEM format to use when connecting to the broker.",
|
||||
InputType: InputTypeText,
|
||||
PropertyName: "clientCertificate",
|
||||
Required: false,
|
||||
Secure: true,
|
||||
},
|
||||
{
|
||||
Label: "Client Key",
|
||||
Element: ElementTypeTextArea,
|
||||
Description: "Client key in PEM format to use when connecting to the broker.",
|
||||
InputType: InputTypeText,
|
||||
PropertyName: "clientKey",
|
||||
Required: false,
|
||||
Secure: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -4,7 +4,17 @@ import { FC, useEffect } from 'react';
|
||||
import { Controller, DeepMap, FieldError, useFormContext } from 'react-hook-form';
|
||||
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
import { Checkbox, Field, Input, RadioButtonList, SecretInput, Select, TextArea, useStyles2 } from '@grafana/ui';
|
||||
import {
|
||||
Checkbox,
|
||||
Field,
|
||||
Input,
|
||||
RadioButtonList,
|
||||
SecretInput,
|
||||
SecretTextArea,
|
||||
Select,
|
||||
TextArea,
|
||||
useStyles2,
|
||||
} from '@grafana/ui';
|
||||
import { NotificationChannelOption, NotificationChannelSecureFields } from 'app/types';
|
||||
|
||||
import { KeyValueMapInput } from './KeyValueMapInput';
|
||||
@ -222,17 +232,21 @@ const OptionInput: FC<Props & { id: string; pathIndex?: string }> = ({
|
||||
name={name}
|
||||
onSelectTemplate={onSelectTemplate}
|
||||
>
|
||||
<TextArea
|
||||
id={id}
|
||||
readOnly={readOnly || useTemplates}
|
||||
invalid={invalid}
|
||||
placeholder={option.placeholder}
|
||||
{...register(name, {
|
||||
required: option.required ? 'Required' : false,
|
||||
validate: (v) =>
|
||||
option.validationRule !== '' ? validateOption(v, option.validationRule, option.required) : true,
|
||||
})}
|
||||
/>
|
||||
{isEncryptedInput ? (
|
||||
<SecretTextArea onReset={() => onResetSecureField?.(nestedKey)} isConfigured />
|
||||
) : (
|
||||
<TextArea
|
||||
id={id}
|
||||
readOnly={readOnly || useTemplates}
|
||||
invalid={invalid}
|
||||
placeholder={option.placeholder}
|
||||
{...register(name, {
|
||||
required: option.required ? 'Required' : false,
|
||||
validate: (v) =>
|
||||
option.validationRule !== '' ? validateOption(v, option.validationRule, option.required) : true,
|
||||
})}
|
||||
/>
|
||||
)}
|
||||
</WrapWithTemplateSelection>
|
||||
);
|
||||
case 'string_array':
|
||||
|
Loading…
Reference in New Issue
Block a user