All Posts

Find Answers
Ask questions. Get answers. Find technical product solutions from passionate members of the Splunk community.

All Posts

Hi everyone, I'm working with the Splunk Add-on for AWS on Splunk Cloud, and I’ve run into an issue when trying to collect CloudWatch Logs from a cross-account AWS setup. After digging through the ... See more...
Hi everyone, I'm working with the Splunk Add-on for AWS on Splunk Cloud, and I’ve run into an issue when trying to collect CloudWatch Logs from a cross-account AWS setup. After digging through the Python code inside the add-on, I discovered that it uses the logGroupName parameter when calling describe_log_streams() via Boto3. However, in cross-account scenarios, AWS requires the use of logGroupIdentifier (with the full ARN of the log group) — and you can’t use both parameters at the same time.   So, even though AWS allows log collection across accounts using logGroupIdentifier, the current implementation in the add-on makes it impossible to use this feature correctly. I was able to identify the exact line of code that causes the issue and verified that simply replacing "logGroupName" with "logGroupIdentifier" solves the problem. Given that I'm on Splunk Cloud, I have a few questions for those with more experience in similar situations: Is it possible to modify that single line of Python code directly in the official add-on deployed in Splunk Cloud (maybe through the UI or some workaround), or is that completely locked down? I could clone the add-on, patch it, and submit it as a custom app — but would running a custom version of the AWS add-on cause issues with future Splunk Support cases? (i.e., would support be denied for data coming from a modified TA?) More broadly, for anyone who’s set up Splunk in cross-account AWS environments: What’s your recommended approach for collecting CloudWatch Logs in this scenario, given the limitations of the official add-on? Thanks in advance for any insights.
Hi @Ara  As others have said, I dont think a map is well placed here, you might find the following useful, which determines if your "someString" is present and filters those which have this. index=... See more...
Hi @Ara  As others have said, I dont think a map is well placed here, you might find the following useful, which determines if your "someString" is present and filters those which have this. index=xyz | rex field=msg "DEBUG\s+\|\s+(?<traceid>[a-f0-9-]{36})" | rex field=msg \"artifact_guid\":\"(?<artifact_guid>[a-f0-9-]{36})\" | rex field=msg \"email_address\":\"(?<email_address>[^\"]+)\" | eval isInteresting=IF(searchmatch("someString"),1,0) | stats max(isInteresting) as isInteresting, values(artifact_guid) as artifact_guid, values(email_address) as email_address by traceid | where isInteresting>0 You might be able to simplify by dealing with the rex separately with field extractions but the premise here is that you use searchmatch to check for your interesting string, then filter out events which do not have it after matching the traceId with the other fields you want.  Did this answer help you? If so, please consider: Adding karma to show it was useful Marking it as the solution if it resolved your issue Commenting if you need any clarification Your feedback encourages the volunteers in this community to continue contributing
Adding to valid @livehybrid points, you should set INDEXED_VALUE=false. It has nothing to do with the issue at hand but without it you won't be able to search for id=123 if then"123" string isn't con... See more...
Adding to valid @livehybrid points, you should set INDEXED_VALUE=false. It has nothing to do with the issue at hand but without it you won't be able to search for id=123 if then"123" string isn't contained within the raw event.
Hi @Charlize  Just to check, did you deploy the fields.conf to your cloud environment, not the UF? Also, are you able to search the field with tstats, such as | tstats count where index=index_abc ... See more...
Hi @Charlize  Just to check, did you deploy the fields.conf to your cloud environment, not the UF? Also, are you able to search the field with tstats, such as | tstats count where index=index_abc by id     Did this answer help you? If so, please consider: Adding karma to show it was useful Marking it as the solution if it resolved your issue Commenting if you need any clarificatiob Your feedback encourages the volunteers in this community to continue contributing.
Added the config for the new metadata field in the inputs.conf file and created a fields.conf file to set the field as indexed=true. Still the field is not showing up on SH. This is done for the clou... See more...
Added the config for the new metadata field in the inputs.conf file and created a fields.conf file to set the field as indexed=true. Still the field is not showing up on SH. This is done for the cloud envi inputs.conf [monitor://D:\Splunk\abc\*.csv] disabled = false index = index_abc sourcetype = src_abc _meta = id::123   fields.conf [id] INDEXED=true
While I fully agree with @yuanliu and @bowesmana that map is most probably not the way to go in this case there is an obvious lack of/improper use of quotes. If you unescape your mapped search you'l... See more...
While I fully agree with @yuanliu and @bowesmana that map is most probably not the way to go in this case there is an obvious lack of/improper use of quotes. If you unescape your mapped search you'll get search index=xyz "$traceid$" AND "REQUEST BODY" | rex field=msg "artifact_guid":"(?<artifact_guid>[a-f0-9-]{36})" | rex field=msg "email_address":"(?<email_address>[^"]+)" | table traceid, artifact_guid, email_address This is not the right syntax for rex command. As far as I remember map won't pass the errors from the mapped search to your outer search - it will just not yield any results. Hence your behaviour.
PYDEN is archived? What's wrong with this approach? Not approved for splunk cloud? 
Totally agree with @bowesmana that there is no benefit of using map in this use case.  I also have a suggestion: Do not bother with rex.  Looking at your regular expression, it is all but certain tha... See more...
Totally agree with @bowesmana that there is no benefit of using map in this use case.  I also have a suggestion: Do not bother with rex.  Looking at your regular expression, it is all but certain that the field msg contains JSON.  This would be much simpler: index=xyz ("someString" OR "REQUEST BODY") ``` Extract the traceid fron the DBUG message containing someString and then from the request body ``` | rex field=msg "DEBUG\s+\|\s+(?<debug_traceid>[a-f0-9-]{36})" | rex field=field_containing_traceid_in_request_body "(?<body_traceid>[a-f0-9-]{36})" | eval traceid=coalesce(debug_traceid, body_traceid) | spath input=msg | stats values(debug_traceid) as debug_traceid values(artifact_guid) as artifact_guid values(email_address) as email_address by traceid | where isnotnull(debug_traceid)
map may not be the best solution here - as to why it's not working, if you just have the map search and nothing after does it return results? Why do you have escaped quotes round the \"$traceid$\" -... See more...
map may not be the best solution here - as to why it's not working, if you just have the map search and nothing after does it return results? Why do you have escaped quotes round the \"$traceid$\" - is your trace id string quoted in the data? Note that unless traceid exists in your map search results, your table statement will have no value for traceid. However, given the somewhat complex quote escaping you are doing to parse data from what appears to be JSON data, I expect the problem is somewhere there. You'd need to give a data example. However, map is generally not a great way to solve a problem, because it's default limit is 10 results and if you do more, each search runs as a separate sequential search, so adds additional load on the indexes/search head. You may be better off using a simple stats command to join the data, e.g. index=xyz "someString" OR "REQUEST BODY" ``` Extract the traceid fron the DBUG message containing someString and then from the request body ``` | rex field=msg "DEBUG\s+\|\s+(?<debug_traceid>[a-f0-9-]{36})" | rex field=field_containing_traceid_in_request_body "(?<body_traceid>[a-f0-9-]{36})" | eval traceid=coalesce(debug_traceid, body_traceid) | rex field=msg "artifact_guid\":\"(?<artifact_guid>[a-f0-9-]{36})" | rex field=msg "email_address\":\"(?<email_address>[^\"]+)" | stats values(debug_traceid) as debug_traceid values(artifact_guid) as artifact_guid values(email_address) as email_address by traceid | where isnotnull(debug_traceid) So this searches both data sets, gets the traceid from both event types and then collects the artifact and email from the body and joins the data sets and then filters out those that do not have a matching someString event.  
Why are you using wildcards if they are not necessary. Your data and your comments say the msg values are defined as  gemini:streaming:info:product:data:responseTime gemini:streaming:info:amaz:sear... See more...
Why are you using wildcards if they are not necessary. Your data and your comments say the msg values are defined as  gemini:streaming:info:product:data:responseTime gemini:streaming:info:amaz:search:response:time (The data shows a slight difference in responseTime vs. response:time compared to your comment) Just use this type of search ... msg IN ("gemini:streaming:info:product:data:responseTime","gemini:streaming:info:amaz:search:response:time")
I am trying to loop over a table and perform a subsearch for each item. I can confirm I am generating the first table with correct values. However the subsearch portion is not returning any results. ... See more...
I am trying to loop over a table and perform a subsearch for each item. I can confirm I am generating the first table with correct values. However the subsearch portion is not returning any results.  Can someone help me figure out where my query is wrong? Would be very much appreciated! index=xyz "someString" | rex field=msg "DEBUG\s+\|\s+(?<traceid>[a-f0-9-]{36})" | table traceid | map search="search index=xyz \"$traceid$\" AND \"REQUEST BODY\" | rex field=msg \"artifact_guid\":\"(?<artifact_guid>[a-f0-9-]{36})\" | rex field=msg \"email_address\":\"(?<email_address>[^\"]+)\" | table traceid, artifact_guid, email_address"
@onthakur  OK, got it, so you only want the events from dataset 2 where there is a matching event from dataset 1. In that case, you can do the stats and retain the X_App_ID using stats values(X_App... See more...
@onthakur  OK, got it, so you only want the events from dataset 2 where there is a matching event from dataset 1. In that case, you can do the stats and retain the X_App_ID using stats values(X_App_ID). I assume there is only ONE X_App_ID per correlation Id. Then you just filter out the unwanted correlation Ids from dataset 2 where there are no X_App_ID events joined. index=masapi (X_App_ID=ScamShield API_NAME=COMBINED_FEATURES NOT externalURL) OR (napResponseMapping) ``` The values(X_App_ID) retains the app id for those events in dataset 1 - which will only include ScamShield ``` | stats values(X_App_ID) as X_App_ID values(accountType) as accountType values(accountSubType) as accountSubType by X_Correlation_ID ``` and this will remove all the correlation ids that did not have a corresponding X_App_ID event in dataset 1 ``` | where isnotnull(X_App_ID)  Hope this helps
The _raw=... line is OUR example based on your data to demonstrate the solution. You MUST not include that in YOUR search, as it makes every event equal to that _raw value.
Hi Team, Currently in my dashboard i am using two separate query for data and search lambda separetly and added to the dashboard 1.I want a combine query which works for both data and search lamb... See more...
Hi Team, Currently in my dashboard i am using two separate query for data and search lambda separetly and added to the dashboard 1.I want a combine query which works for both data and search lambda together an display reult as below GET /data/v1/amaz 1601 GET /search/v1/amaz 159 GET /data/v1/product 3 GET /search/v1/product 186 GET /data/v1/hack 373 GET /data/v1/cb1 1127 GET /search/v1/hack 297   Data lambda query: index=np source IN ("/aws/lambda/p-api-data-test-*") "gemini:streaming:info:*:*:responseTime" | eval Entity = requestType . "/data/" . entity | stats sum(responseTime) as totalResponseTime, avg(responseTime) as avgResponseTime, count as totalTimeBuckets by Entity | eval avgResponseTime = round(avgResponseTime, 2) | rename totalResponseTime as "totalResponseTime(ms)", avgResponseTime as "avgResponseTime(ms)", totalTimeBuckets as "totalTimeBuckets" | table Entity "avgResponseTime(ms)" | sort - "totalResponseTime(ms)" Data lambda Event: { [-] apiResponseTime: 222 awsRequestId: client: Joshu domain: product entity: product hostname: level: 30 msg: gemini:streaming:info:product:data:responseTime pid: 8 queryParams: { [+] } requestType: GET responseTime: 285 time: 2025-05-01T21:59:06.588Z v: 0 } Search lambda: index=np source="/aws/lambda/p-api-search-test-*" "gemini:streaming:info:*:search:response:time" | rex field=source "/aws/lambda/pdp-pc-api-search-test-(?<entity>[^/]+)" | eval Entity = requestType . " search/" . entity | stats sum(responseTime) as totalResponseTime, avg(responseTime) as avgResponseTime, count as totalTimeBuckets by Entity | eval avgResponseTime = round(avgResponseTime, 2) | rename totalResponseTime as "totalResponseTime(ms)", avgResponseTime as "avgResponseTime(ms)", totalTimeBuckets as "totalTimeBuckets" | table Entity "avgResponseTime(ms)" | sort - "totalResponseTime(ms)" Search lambda Event: { [-] apiResponseTime: 146 client: Joshua.Be domain: product entity: amaz level: 30 msg: gemini:streaming:info:amaz:search:response:time pid: 8 queryHits: 50 queryParams: { [+] } requestType: GET responseTime: 149056 time: 2025-05-01T22:01:35.622Z v: 0 } 2.Data api msg: will be: gemini:streaming:info:product:data:responseTime Search api msg: will be: gemini:streaming:info:amaz:search:responseTime so in query i added keyword as "gemini:streaming:info:*:*:responseTime" but througing error as  "The term '"gemini:streaming:info:*:*:responseTime"' contains a wildcard in the middle of a word or string. This might cause inconsistent results if the characters that the wildcard represents include punctuation"  
1. Line breaking is happening before sedcmd kicks in so you must adjust your line breaker to work on a "non-trimmed" data and then remove the header/footer from the broken events. 2. Your line break... See more...
1. Line breaking is happening before sedcmd kicks in so you must adjust your line breaker to work on a "non-trimmed" data and then remove the header/footer from the broken events. 2. Your line breaker doesn't account for new line characters. 3. You are aware that if you simply break at curly braces you can't have any more levels in your json structure because it will break your breaking, right? So you should first break at ([\r\n\s]+){ Then you can use sedcmd to remove the dangling [\s\n\r]*\][\s\n\r\]*} part. And use a transform to drop (send to nullqueue) the header event.
We've logs coming to HEC as nested JSON in chunks; We're trying to break them down into individual events at the HEC level before indexing them in Splunk. I had some success to remove the header/foot... See more...
We've logs coming to HEC as nested JSON in chunks; We're trying to break them down into individual events at the HEC level before indexing them in Splunk. I had some success to remove the header/footer with props.conf and breaking the events, but it doesn't work completely. Most of the logs are not broken into individual events. Sample events -  { "logs": [ { "type": "https", "timestamp": "2025-03-17T23:55:54.626915Z", "elb": "someELB", "client_ip": "10.xx.xx.xx", "client_port": 123456, "target_ip": "10.xx.xx.xx", "target_port": 123456, "request_processing_time": 0, "target_processing_time": 0.003, "response_processing_time": 0, "elb_status_code": 200, "target_status_code": 200, "received_bytes": 69, "sent_bytes": 3222, "request": "GET https://xyz.com", "user_agent": "-", "ssl_cipher": "ECDHE-RSA-AE", "ssl_protocol": "TLSv1.2", "target_group_arn": "arn:aws:elasticloadbalancing:us-west-2:XXXXX:targetgroup/XXXXX", "trace_id": "Root=XXXX" }, { "type": "https", "timestamp": "2025-03-17T23:56:00.285547Z", "elb": "someELB", "client_ip": "10.xx.xx.xx", "client_port": 123456, "target_ip": "10.xx.xx.xx", "target_port": 123456, "request_processing_time": 0, "target_processing_time": 0.003, "response_processing_time": 0, "elb_status_code": 200, "target_status_code": 200, "received_bytes": 69, "sent_bytes": 3222, "request": "GET https://xyz.com", "user_agent": "-", "ssl_cipher": "ECDHE-RSA-AE", "ssl_protocol": "TLSv1.2", "target_group_arn": "arn:aws:elasticloadbalancing:us-west-2:XXXXX:targetgroup/XXXXX", "trace_id": "Root=XXXX" }, { "type": "https", "timestamp": "2025-03-17T23:57:39.574741Z", "elb": "someELB", "client_ip": "10.xx.xx.xx", "client_port": 123456, "target_ip": "10.xx.xx.xx", "target_port": 123456, "request_processing_time": 0, "target_processing_time": 0.003, "response_processing_time": 0, "elb_status_code": 200, "target_status_code": 200, "received_bytes": 69, "sent_bytes": 3222, "request": "GET https://xyz.com", "user_agent": "-", "ssl_cipher": "ECDHE-RSA-AE", "ssl_protocol": "TLSv1.2", "target_group_arn": "arn:aws:elasticloadbalancing:us-west-2:XXXXX:targetgroup/XXXXX", "trace_id": "XXXX" } ] }  I am trying to get   { "type": "https", "timestamp": "2025-03-17T23:55:54.626915Z", "elb": "someELB", "client_ip": "10.xx.xx.xx", "client_port": 123456, "target_ip": "10.xx.xx.xx", "target_port": 123456, "request_processing_time": 0, "target_processing_time": 0.003, "response_processing_time": 0, "elb_status_code": 200, "target_status_code": 200, "received_bytes": 69, "sent_bytes": 3222, "request": "GET https://xyz.com", "user_agent": "-", "ssl_cipher": "ECDHE-RSA-AE", "ssl_protocol": "TLSv1.2", "target_group_arn": "arn:aws:elasticloadbalancing:us-west-2:XXXXX:targetgroup/XXXXX", "trace_id": "Root=XXXX" } { "type": "https", "timestamp": "2025-03-17T23:56:00.285547Z", "elb": "someELB", "client_ip": "10.xx.xx.xx", "client_port": 123456, "target_ip": "10.xx.xx.xx", "target_port": 123456, "request_processing_time": 0, "target_processing_time": 0.003, "response_processing_time": 0, "elb_status_code": 200, "target_status_code": 200, "received_bytes": 69, "sent_bytes": 3222, "request": "GET https://xyz.com", "user_agent": "-", "ssl_cipher": "ECDHE-RSA-AE", "ssl_protocol": "TLSv1.2", "target_group_arn": "arn:aws:elasticloadbalancing:us-west-2:XXXXX:targetgroup/XXXXX", "trace_id": "Root=XXXX" } { "type": "https", "timestamp": "2025-03-17T23:57:39.574741Z", "elb": "someELB", "client_ip": "10.xx.xx.xx", "client_port": 123456, "target_ip": "10.xx.xx.xx", "target_port": 123456, "request_processing_time": 0, "target_processing_time": 0.003, "response_processing_time": 0, "elb_status_code": 200, "target_status_code": 200, "received_bytes": 69, "sent_bytes": 3222, "request": "GET https://xyz.com", "user_agent": "-", "ssl_cipher": "ECDHE-RSA-AE", "ssl_protocol": "TLSv1.2", "target_group_arn": "arn:aws:elasticloadbalancing:us-west-2:XXXXX:targetgroup/XXXXX", "trace_id": "XXXX" }   props.conf [source::http:lblogs] SHOULD_LINEMERGE = false SEDCMD-remove_prefix = s/^\{\s*\"logs\"\:\s+\[//g SEDCMD-remove_suffix = s/\]\}$//g LINE_BREAKER = \}(,\s+)\{ NO_BINARY_CHECK = true TIME_PREFIX = \"timestamp\":\s+\" pulldown_type = true MAX_TIMESTAMP_LOOKAHEAD = 100 TIME_FORMAT = %Y-%m-%dT%H:%M:%S.%6N TRUNCATE = 1000000   Current Result in Splunk are below in the attached screenshot. The header ({ logs [) and footer are removed from events,  but then split (line break) maybe just working for one event in the chunk and others are ignored.  
Hi @DarthHerm  Is this what you are looking for?  From your original search you should be able to do: | eval params=json_array_to_mv(json_extract(_raw,"parameters")) | eval newParams="{}" | ... See more...
Hi @DarthHerm  Is this what you are looking for?  From your original search you should be able to do: | eval params=json_array_to_mv(json_extract(_raw,"parameters")) | eval newParams="{}" | foreach mode=multivalue params [| eval newParams=json_set(newParams,json_extract(<<ITEM>>,"name"),json_extract(<<ITEM>>,"value"))] | spath input=newParams | table accessDate, userName, serverHost, @SparklingTypeId, @PageSize, @PageNumber Below is a full example to get you started: | windbag | head 1 | eval _raw="{\"auditResultSets\":null,\"schema\":\"com\",\"storedProcedureName\":\"SpongeGetBySearchCriteria\",\"commandText\":\"com.SpongeGetBySearchCriteria\",\"Locking\":null,\"commandType\":4,\"parameters\":[{\"name\":\"@RETURN_VALUE\",\"value\":0},{\"name\":\"@SpongeTypeId\",\"value\":null},{\"name\":\"@CustomerNameStartWith\",\"value\":null},{\"name\":\"@IsAssigned\",\"value\":null},{\"name\":\"@IsAssignedToIdIsNULL\",\"value\":false},{\"name\":\"@SpongeStatusIdsCSV\",\"value\":\",1,\"},{\"name\":\"@RequestingValueId\",\"value\":null},{\"name\":\"@RequestingStaffId\",\"value\":null},{\"name\":\"@IsParamOther\",\"value\":false},{\"name\":\"@AssignedToId\",\"value\":null},{\"name\":\"@MALLLocationId\",\"value\":8279},{\"name\":\"@AssignedDateFrom\",\"value\":null},{\"name\":\"@AssignedDateTo\",\"value\":null},{\"name\":\"@RequestDateFrom\",\"value\":null},{\"name\":\"@RequestDateTo\",\"value\":null},{\"name\":\"@DueDateFrom\",\"value\":null},{\"name\":\"@DueDateTo\",\"value\":null},{\"name\":\"@ExcludeCustomerFlagTypeIdsCSV\",\"value\":\",1,\"},{\"name\":\"@PageSize\",\"value\":25},{\"name\":\"@PageNumber\",\"value\":1},{\"name\":\"@SortColumnName\",\"value\":\"RequestDate\"},{\"name\":\"@SortDirection\",\"value\":\"DESC\"},{\"name\":\"@HasAnySparkling\",\"value\":null},{\"name\":\"@SparklingTypeId\",\"value\":null},{\"name\":\"@SparklingSubTypeId\",\"value\":null},{\"name\":\"@SparklingStatusId\",\"value\":null},{\"name\":\"@SparklingDateFrom\",\"value\":null},{\"name\":\"@SparklingDateTo\",\"value\":null},{\"name\":\"@SupervisorId\",\"value\":null},{\"name\":\"@Debug\",\"value\":null}],\"serverIPAddress\":\"255.255.000.000\",\"serverHost\":\"WEBSERVER\",\"clientIPAddress\":\"255.255.255.255\",\"sourceSystem\":\"WebSite\",\"module\":\"Vendor.Product.BLL.Community\",\"accessDate\":\"2025-04-30T15:34:33.3568918-06:00\",\"userId\":3231,\"userName\":\"PeterVenkman\",\"traceInformation\":[{\"type\":\"Page\",\"class\":\"Vendor.Product.Web.UI.Website.Community.Operations.SpongeSearch\",\"method\":\"Page_Load\"},{\"type\":\"Manager\",\"class\":\"Vendor.Product.BLL.Community.SpongeManager\",\"method\":\"SpongeSearch\"}]}" | fields _raw | spath | eval params=json_array_to_mv(json_extract(_raw,"parameters")) | eval newParams="{}" | foreach mode=multivalue params [| eval newParams=json_set(newParams,json_extract(<<ITEM>>,"name"),json_extract(<<ITEM>>,"value"))] | spath input=newParams | table accessDate, userName, serverHost, @SparklingTypeId, @PageSize, @PageNumber  Did this answer help you? If so, please consider: Adding karma to show it was useful Marking it as the solution if it resolved your issue Commenting if you need any clarification Your feedback encourages the volunteers in this community to continue contributing
Thank you both. This was really helpful.
TLS can be sensitive to errors and it's relatively easy to break your environment so I'd advise you to do some lab work (not necessarily with Splunk; apache httpd for example is a very well documment... See more...
TLS can be sensitive to errors and it's relatively easy to break your environment so I'd advise you to do some lab work (not necessarily with Splunk; apache httpd for example is a very well docummented solution you can use to get experience with real-world third-party CA - you can use Let's Encrypt for free). But back to your question - as a rule of thumb, the side which identity you need to verify must use a certificate trusted by the other side. So typically - like with most of the HTTPS servers over the internet - the server presents a certificate issued by a CA that the client trusts. That's the basic minimal setup which allows the client to be sure that the server is who it claims to be and then allows it to negotiate a protected encrypted connection within which it can, for example, authenticate itself using normal HTTP means. This is the way it works normally between your browser and most internet services - your browser has a list of trusted RootCAs. The server you're trying to connect to presents a certificate with certificate chain tracing back to a RootCA your browser trusts. The browser checks if the certificate is valid, matches the server you wanted to connect to and the purpose for which the certificate was issued (so you can't just set up a www server with a certificate meant for S/MIME mail encryption). Your browser negotiates an encrypted connection with the server and within this connection, since you can now trust that the server is who it claims to be, you authenticate yourself using login/password or whatever other method you use because you know that you're talking to a known party over a secure channel. That's a typical use case and it matches the typical use case with UF as a client (both as a client for DS as well as a client connecting to the indexer/HF). You need to have a certificate issued by a trusted CA (or having a certification chain back to trusted CA) on the server (DS, idx and so on) and have the UF trust the CA certificate. In this case all UFs just need to have this one CA certificate configured as a trusted CA. But you can also if needed configure client's authentication. In such case each UF would have its own certificate which in this case would need to be issued by a CA trusted by the server. In this scenario, typically referred to as mTLS or mutual authentication, each side verifies the identity of the other endpoint so each unique subject (in our case each UF) would require a separate individual cert. This scenario is however difficult to manage without a lot of administrative overhead (just tracking expiration dates of dozens of certs is enough of a headache, not mentioning renewing them and installing) so it's not commonly used. But it's possible.
Ok, so just to summarize to make sure I understand, I would create a custom cert (either self-signed or third-party) and configure the DS to use that cert per the links I had above. Then I would conf... See more...
Ok, so just to summarize to make sure I understand, I would create a custom cert (either self-signed or third-party) and configure the DS to use that cert per the links I had above. Then I would configure the UFs to trust that cert's CA in their deploymentclient.conf file.  If I understand correctly, I'm only creating the one custom cert for the deployment server itself. The UFs don't need their own cert, they only need to trust the CA for that cert I created for the DS. Is that correct?  (Sorry for the pedantry, I'm just unsure if I fully understand the cert process in general and don't want to assume I understand then break my environment)