Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
S
spring-boot-admin
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
openSource
spring-boot-admin
Commits
7f2b16d1
Commit
7f2b16d1
authored
Nov 16, 2017
by
Johannes Edmeier
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add option to configure the sanitized metadata keys
fixes #590
parent
e15d7d2d
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
434 additions
and
292 deletions
+434
-292
server.adoc
spring-boot-admin-docs/src/main/asciidoc/server.adoc
+6
-1
AdminServerProperties.java
.../codecentric/boot/admin/config/AdminServerProperties.java
+13
-0
AdminServerWebConfiguration.java
...entric/boot/admin/config/AdminServerWebConfiguration.java
+112
-102
ApplicationBeanSerializerModifier.java
...boot/admin/jackson/ApplicationBeanSerializerModifier.java
+34
-0
ApplicationDeserializer.java
...decentric/boot/admin/jackson/ApplicationDeserializer.java
+51
-0
SanitizingMapSerializer.java
...decentric/boot/admin/jackson/SanitizingMapSerializer.java
+48
-0
Application.java
...ain/java/de/codecentric/boot/admin/model/Application.java
+0
-81
ApplicationJacksonTest.java
...odecentric/boot/admin/jackson/ApplicationJacksonTest.java
+113
-0
ApplicationTest.java
...java/de/codecentric/boot/admin/model/ApplicationTest.java
+44
-106
RegistryControllerTest.java
...ntric/boot/admin/registry/web/RegistryControllerTest.java
+13
-2
No files found.
spring-boot-admin-docs/src/main/asciidoc/server.adoc
View file @
7f2b16d1
...
...
@@ -27,7 +27,12 @@
| spring.boot.admin.routes.endpoints
| The enpoints which will be available via spring boot admin zuul proxy. If you write ui modules using other endpoints you need to add them.
| `"env, metrics, trace, dump, jolokia, info, configprops, activiti, logfile, refresh, flyway, liquibase, loggers"`
| `"env", "metrics", "trace", "dump", "jolokia", "info", "configprops", "activiti", "logfile", "refresh", "flyway", "liquibase", "loggers"`
| spring.boot.admin.metadata-keys-to-sanitize
| Metadata values for the keys matching these regex patterns will be sanitized in all json output.
| `".*password$", ".*secret$", ".*key$", ".*$token$", ".*credentials.*", ".*vcap_services$"`
|===
include::server-discovery.adoc[]
...
...
spring-boot-admin-server/src/main/java/de/codecentric/boot/admin/config/AdminServerProperties.java
View file @
7f2b16d1
...
...
@@ -16,6 +16,11 @@ public class AdminServerProperties {
private
RoutesProperties
routes
=
new
RoutesProperties
();
/**
* The metadata keys which should be sanitized when serializing to json
*/
private
String
[]
metadataKeysToSanitize
=
new
String
[]{
".*password$"
,
".*secret$"
,
".*key$"
,
".*$token$"
,
".*credentials.*"
,
".*vcap_services$"
};
public
void
setContextPath
(
String
pathPrefix
)
{
if
(!
pathPrefix
.
startsWith
(
"/"
)
||
pathPrefix
.
endsWith
(
"/"
))
{
throw
new
IllegalArgumentException
(
"ContextPath must start with '/' and not end with '/'"
);
...
...
@@ -27,6 +32,14 @@ public class AdminServerProperties {
return
contextPath
;
}
public
String
[]
getMetadataKeysToSanitize
()
{
return
metadataKeysToSanitize
;
}
public
void
setMetadataKeysToSanitize
(
String
[]
metadataKeysToSanitize
)
{
this
.
metadataKeysToSanitize
=
metadataKeysToSanitize
;
}
public
MonitorProperties
getMonitor
()
{
return
monitor
;
}
...
...
spring-boot-admin-server/src/main/java/de/codecentric/boot/admin/config/AdminServerWebConfiguration.java
View file @
7f2b16d1
...
...
@@ -36,12 +36,17 @@ import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import
org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
com.fasterxml.jackson.databind.module.SimpleModule
;
import
de.codecentric.boot.admin.event.ClientApplicationDeregisteredEvent
;
import
de.codecentric.boot.admin.event.ClientApplicationRegisteredEvent
;
import
de.codecentric.boot.admin.event.RoutesOutdatedEvent
;
import
de.codecentric.boot.admin.jackson.ApplicationBeanSerializerModifier
;
import
de.codecentric.boot.admin.jackson.ApplicationDeserializer
;
import
de.codecentric.boot.admin.jackson.SanitizingMapSerializer
;
import
de.codecentric.boot.admin.journal.ApplicationEventJournal
;
import
de.codecentric.boot.admin.journal.web.JournalController
;
import
de.codecentric.boot.admin.model.Application
;
import
de.codecentric.boot.admin.registry.ApplicationRegistry
;
import
de.codecentric.boot.admin.registry.web.RegistryController
;
import
de.codecentric.boot.admin.web.AdminController
;
...
...
@@ -51,107 +56,112 @@ import de.codecentric.boot.admin.web.servlet.resource.PreferMinifiedFilteringRes
import
de.codecentric.boot.admin.web.servlet.resource.ResourcePatternResolvingResourceResolver
;
@Configuration
public
class
AdminServerWebConfiguration
extends
WebMvcConfigurerAdapter
implements
ApplicationContextAware
{
private
final
ApplicationEventPublisher
publisher
;
private
final
ServerProperties
server
;
private
final
ResourcePatternResolver
resourcePatternResolver
;
private
final
AdminServerProperties
adminServerProperties
;
private
ApplicationContext
applicationContext
;
public
AdminServerWebConfiguration
(
ApplicationEventPublisher
publisher
,
ServerProperties
server
,
ResourcePatternResolver
resourcePatternResolver
,
AdminServerProperties
adminServerProperties
)
{
this
.
publisher
=
publisher
;
this
.
server
=
server
;
this
.
resourcePatternResolver
=
resourcePatternResolver
;
this
.
adminServerProperties
=
adminServerProperties
;
}
@Override
public
void
setApplicationContext
(
ApplicationContext
applicationContext
)
{
this
.
applicationContext
=
applicationContext
;
}
@Override
public
void
extendMessageConverters
(
List
<
HttpMessageConverter
<?>>
converters
)
{
if
(!
hasConverter
(
converters
,
MappingJackson2HttpMessageConverter
.
class
))
{
ObjectMapper
objectMapper
=
Jackson2ObjectMapperBuilder
.
json
()
.
applicationContext
(
this
.
applicationContext
).
build
();
converters
.
add
(
new
MappingJackson2HttpMessageConverter
(
objectMapper
));
}
}
private
boolean
hasConverter
(
List
<
HttpMessageConverter
<?>>
converters
,
Class
<?
extends
HttpMessageConverter
<?>>
clazz
)
{
for
(
HttpMessageConverter
<?>
converter
:
converters
)
{
if
(
clazz
.
isInstance
(
converter
))
{
return
true
;
}
}
return
false
;
}
@Override
public
void
addResourceHandlers
(
ResourceHandlerRegistry
registry
)
{
registry
.
addResourceHandler
(
adminServerProperties
.
getContextPath
()
+
"/**"
)
.
addResourceLocations
(
"classpath:/META-INF/spring-boot-admin-server-ui/"
)
.
resourceChain
(
true
)
.
addResolver
(
new
PreferMinifiedFilteringResourceResolver
(
".min"
));
registry
.
addResourceHandler
(
adminServerProperties
.
getContextPath
()
+
"/all-modules.css"
)
.
resourceChain
(
true
)
.
addResolver
(
new
ResourcePatternResolvingResourceResolver
(
resourcePatternResolver
,
"classpath*:/META-INF/spring-boot-admin-server-ui/*/module.css"
))
.
addResolver
(
new
ConcatenatingResourceResolver
(
"\n"
.
getBytes
()));
registry
.
addResourceHandler
(
adminServerProperties
.
getContextPath
()
+
"/all-modules.js"
)
.
resourceChain
(
true
)
.
addResolver
(
new
ResourcePatternResolvingResourceResolver
(
resourcePatternResolver
,
"classpath*:/META-INF/spring-boot-admin-server-ui/*/module.js"
))
.
addResolver
(
new
PreferMinifiedFilteringResourceResolver
(
".min"
))
.
addResolver
(
new
ConcatenatingResourceResolver
(
";\n"
.
getBytes
()));
}
@Override
public
void
addViewControllers
(
ViewControllerRegistry
registry
)
{
String
contextPath
=
adminServerProperties
.
getContextPath
();
if
(
StringUtils
.
hasText
(
contextPath
))
{
registry
.
addRedirectViewController
(
contextPath
,
server
.
getPath
(
contextPath
)
+
"/"
);
}
registry
.
addViewController
(
contextPath
+
"/"
).
setViewName
(
"forward:index.html"
);
}
@Bean
public
PrefixHandlerMapping
prefixHandlerMapping
()
{
Map
<
String
,
Object
>
beans
=
applicationContext
.
getBeansWithAnnotation
(
AdminController
.
class
);
PrefixHandlerMapping
prefixHandlerMapping
=
new
PrefixHandlerMapping
(
beans
.
values
().
toArray
(
new
Object
[
beans
.
size
()]));
prefixHandlerMapping
.
setPrefix
(
adminServerProperties
.
getContextPath
());
return
prefixHandlerMapping
;
}
@Bean
@ConditionalOnMissingBean
public
RegistryController
registryController
(
ApplicationRegistry
applicationRegistry
)
{
return
new
RegistryController
(
applicationRegistry
);
}
@Bean
@ConditionalOnMissingBean
public
JournalController
journalController
(
ApplicationEventJournal
applicationEventJournal
)
{
return
new
JournalController
(
applicationEventJournal
);
}
@EventListener
public
void
onClientApplicationRegistered
(
ClientApplicationRegisteredEvent
event
)
{
publisher
.
publishEvent
(
new
RoutesOutdatedEvent
());
}
@EventListener
public
void
onClientApplicationDeregistered
(
ClientApplicationDeregisteredEvent
event
)
{
publisher
.
publishEvent
(
new
RoutesOutdatedEvent
());
}
public
class
AdminServerWebConfiguration
extends
WebMvcConfigurerAdapter
implements
ApplicationContextAware
{
private
final
ApplicationEventPublisher
publisher
;
private
final
ServerProperties
server
;
private
final
ResourcePatternResolver
resourcePatternResolver
;
private
final
AdminServerProperties
adminServerProperties
;
private
ApplicationContext
applicationContext
;
public
AdminServerWebConfiguration
(
ApplicationEventPublisher
publisher
,
ServerProperties
server
,
ResourcePatternResolver
resourcePatternResolver
,
AdminServerProperties
adminServerProperties
)
{
this
.
publisher
=
publisher
;
this
.
server
=
server
;
this
.
resourcePatternResolver
=
resourcePatternResolver
;
this
.
adminServerProperties
=
adminServerProperties
;
}
@Override
public
void
setApplicationContext
(
ApplicationContext
applicationContext
)
{
this
.
applicationContext
=
applicationContext
;
}
@Override
public
void
extendMessageConverters
(
List
<
HttpMessageConverter
<?>>
converters
)
{
if
(!
hasConverter
(
converters
,
MappingJackson2HttpMessageConverter
.
class
))
{
ObjectMapper
objectMapper
=
Jackson2ObjectMapperBuilder
.
json
()
.
applicationContext
(
this
.
applicationContext
)
.
build
();
converters
.
add
(
new
MappingJackson2HttpMessageConverter
(
objectMapper
));
}
}
private
boolean
hasConverter
(
List
<
HttpMessageConverter
<?>>
converters
,
Class
<?
extends
HttpMessageConverter
<?>>
clazz
)
{
for
(
HttpMessageConverter
<?>
converter
:
converters
)
{
if
(
clazz
.
isInstance
(
converter
))
{
return
true
;
}
}
return
false
;
}
@Override
public
void
addResourceHandlers
(
ResourceHandlerRegistry
registry
)
{
registry
.
addResourceHandler
(
adminServerProperties
.
getContextPath
()
+
"/**"
)
.
addResourceLocations
(
"classpath:/META-INF/spring-boot-admin-server-ui/"
)
.
resourceChain
(
true
)
.
addResolver
(
new
PreferMinifiedFilteringResourceResolver
(
".min"
));
registry
.
addResourceHandler
(
adminServerProperties
.
getContextPath
()
+
"/all-modules.css"
)
.
resourceChain
(
true
)
.
addResolver
(
new
ResourcePatternResolvingResourceResolver
(
resourcePatternResolver
,
"classpath*:/META-INF/spring-boot-admin-server-ui/*/module.css"
))
.
addResolver
(
new
ConcatenatingResourceResolver
(
"\n"
.
getBytes
()));
registry
.
addResourceHandler
(
adminServerProperties
.
getContextPath
()
+
"/all-modules.js"
)
.
resourceChain
(
true
)
.
addResolver
(
new
ResourcePatternResolvingResourceResolver
(
resourcePatternResolver
,
"classpath*:/META-INF/spring-boot-admin-server-ui/*/module.js"
))
.
addResolver
(
new
PreferMinifiedFilteringResourceResolver
(
".min"
))
.
addResolver
(
new
ConcatenatingResourceResolver
(
";\n"
.
getBytes
()));
}
@Override
public
void
addViewControllers
(
ViewControllerRegistry
registry
)
{
String
contextPath
=
adminServerProperties
.
getContextPath
();
if
(
StringUtils
.
hasText
(
contextPath
))
{
registry
.
addRedirectViewController
(
contextPath
,
server
.
getPath
(
contextPath
)
+
"/"
);
}
registry
.
addViewController
(
contextPath
+
"/"
).
setViewName
(
"forward:index.html"
);
}
@Bean
public
SimpleModule
adminJacksonModule
()
{
SimpleModule
module
=
new
SimpleModule
();
module
.
addDeserializer
(
Application
.
class
,
new
ApplicationDeserializer
());
module
.
setSerializerModifier
(
new
ApplicationBeanSerializerModifier
(
new
SanitizingMapSerializer
(
adminServerProperties
.
getMetadataKeysToSanitize
())))
;
return
module
;
}
@Bean
public
PrefixHandlerMapping
prefixHandlerMapping
()
{
Map
<
String
,
Object
>
beans
=
applicationContext
.
getBeansWithAnnotation
(
AdminController
.
class
);
PrefixHandlerMapping
prefixHandlerMapping
=
new
PrefixHandlerMapping
(
beans
.
values
().
toArray
(
new
Object
[
beans
.
size
()]));
prefixHandlerMapping
.
setPrefix
(
adminServerProperties
.
getContextPath
());
return
prefixHandlerMapping
;
}
@Bean
@ConditionalOnMissingBean
public
RegistryController
registryController
(
ApplicationRegistry
applicationRegistry
)
{
return
new
RegistryController
(
applicationRegistry
);
}
@Bean
@ConditionalOnMissingBean
public
JournalController
journalController
(
ApplicationEventJournal
applicationEventJournal
)
{
return
new
JournalController
(
applicationEventJournal
);
}
@EventListener
public
void
onClientApplicationRegistered
(
ClientApplicationRegisteredEvent
event
)
{
publisher
.
publishEvent
(
new
RoutesOutdatedEvent
());
}
@EventListener
public
void
onClientApplicationDeregistered
(
ClientApplicationDeregisteredEvent
event
)
{
publisher
.
publishEvent
(
new
RoutesOutdatedEvent
());
}
}
spring-boot-admin-server/src/main/java/de/codecentric/boot/admin/jackson/ApplicationBeanSerializerModifier.java
0 → 100644
View file @
7f2b16d1
package
de
.
codecentric
.
boot
.
admin
.
jackson
;
import
de.codecentric.boot.admin.model.Application
;
import
java.util.List
;
import
com.fasterxml.jackson.databind.BeanDescription
;
import
com.fasterxml.jackson.databind.JsonSerializer
;
import
com.fasterxml.jackson.databind.SerializationConfig
;
import
com.fasterxml.jackson.databind.ser.BeanPropertyWriter
;
import
com.fasterxml.jackson.databind.ser.BeanSerializerModifier
;
public
class
ApplicationBeanSerializerModifier
extends
BeanSerializerModifier
{
private
final
JsonSerializer
<
Object
>
metadataSerializer
;
@SuppressWarnings
(
"unchecked"
)
public
ApplicationBeanSerializerModifier
(
SanitizingMapSerializer
metadataSerializer
)
{
this
.
metadataSerializer
=
(
JsonSerializer
<
Object
>)
(
JsonSerializer
)
metadataSerializer
;
}
@Override
public
List
<
BeanPropertyWriter
>
changeProperties
(
SerializationConfig
config
,
BeanDescription
beanDesc
,
List
<
BeanPropertyWriter
>
beanProperties
)
{
if
(!
Application
.
class
.
isAssignableFrom
(
beanDesc
.
getBeanClass
()))
{
return
beanProperties
;
}
for
(
BeanPropertyWriter
beanProperty
:
beanProperties
)
{
if
(
"metadata"
.
equals
(
beanProperty
.
getName
()))
{
beanProperty
.
assignSerializer
(
metadataSerializer
);
}
}
return
beanProperties
;
}
}
spring-boot-admin-server/src/main/java/de/codecentric/boot/admin/jackson/ApplicationDeserializer.java
0 → 100644
View file @
7f2b16d1
package
de
.
codecentric
.
boot
.
admin
.
jackson
;
import
de.codecentric.boot.admin.model.Application
;
import
java.io.IOException
;
import
java.util.Iterator
;
import
java.util.Map
;
import
com.fasterxml.jackson.core.JsonParser
;
import
com.fasterxml.jackson.core.JsonProcessingException
;
import
com.fasterxml.jackson.databind.DeserializationContext
;
import
com.fasterxml.jackson.databind.JsonNode
;
import
com.fasterxml.jackson.databind.deser.std.StdDeserializer
;
public
class
ApplicationDeserializer
extends
StdDeserializer
<
Application
>
{
private
static
final
long
serialVersionUID
=
1L
;
public
ApplicationDeserializer
()
{
super
(
Application
.
class
);
}
@Override
public
Application
deserialize
(
JsonParser
p
,
DeserializationContext
ctxt
)
throws
IOException
,
JsonProcessingException
{
JsonNode
node
=
p
.
readValueAsTree
();
Application
.
Builder
builder
=
Application
.
create
(
node
.
get
(
"name"
).
asText
());
if
(
node
.
has
(
"url"
))
{
String
url
=
node
.
get
(
"url"
).
asText
();
builder
.
withHealthUrl
(
url
.
replaceFirst
(
"/+$"
,
""
)
+
"/health"
).
withManagementUrl
(
url
);
}
else
{
if
(
node
.
has
(
"healthUrl"
))
{
builder
.
withHealthUrl
(
node
.
get
(
"healthUrl"
).
asText
());
}
if
(
node
.
has
(
"managementUrl"
))
{
builder
.
withManagementUrl
(
node
.
get
(
"managementUrl"
).
asText
());
}
if
(
node
.
has
(
"serviceUrl"
))
{
builder
.
withServiceUrl
(
node
.
get
(
"serviceUrl"
).
asText
());
}
}
if
(
node
.
has
(
"metadata"
))
{
Iterator
<
Map
.
Entry
<
String
,
JsonNode
>>
it
=
node
.
get
(
"metadata"
).
fields
();
while
(
it
.
hasNext
())
{
Map
.
Entry
<
String
,
JsonNode
>
entry
=
it
.
next
();
builder
.
addMetadata
(
entry
.
getKey
(),
entry
.
getValue
().
asText
());
}
}
return
builder
.
build
();
}
}
spring-boot-admin-server/src/main/java/de/codecentric/boot/admin/jackson/SanitizingMapSerializer.java
0 → 100644
View file @
7f2b16d1
package
de
.
codecentric
.
boot
.
admin
.
jackson
;
import
java.io.IOException
;
import
java.util.Map
;
import
java.util.regex.Pattern
;
import
com.fasterxml.jackson.core.JsonGenerator
;
import
com.fasterxml.jackson.databind.SerializerProvider
;
import
com.fasterxml.jackson.databind.ser.std.StdSerializer
;
public
class
SanitizingMapSerializer
extends
StdSerializer
<
Map
<
String
,
String
>>
{
private
static
final
long
serialVersionUID
=
1L
;
private
final
Pattern
[]
keysToSanitize
;
@SuppressWarnings
(
"unchecked"
)
public
SanitizingMapSerializer
(
String
[]
patterns
)
{
super
((
Class
<
Map
<
String
,
String
>>)
(
Class
<?>)
Map
.
class
);
keysToSanitize
=
createPatterns
(
patterns
);
}
private
static
Pattern
[]
createPatterns
(
String
...
keys
)
{
Pattern
[]
patterns
=
new
Pattern
[
keys
.
length
];
for
(
int
i
=
0
;
i
<
keys
.
length
;
i
++)
{
patterns
[
i
]
=
Pattern
.
compile
(
keys
[
i
],
Pattern
.
CASE_INSENSITIVE
);
}
return
patterns
;
}
@Override
public
void
serialize
(
Map
<
String
,
String
>
value
,
JsonGenerator
gen
,
SerializerProvider
provider
)
throws
IOException
{
gen
.
writeStartObject
();
for
(
Map
.
Entry
<
String
,
String
>
entry
:
value
.
entrySet
())
{
gen
.
writeStringField
(
entry
.
getKey
(),
sanitize
(
entry
.
getKey
(),
entry
.
getValue
()));
}
gen
.
writeEndObject
();
}
private
String
sanitize
(
String
key
,
String
value
)
{
for
(
Pattern
pattern
:
this
.
keysToSanitize
)
{
if
(
pattern
.
matcher
(
key
).
matches
())
{
return
(
value
==
null
?
null
:
"******"
);
}
}
return
value
;
}
}
\ No newline at end of file
spring-boot-admin-server/src/main/java/de/codecentric/boot/admin/model/Application.java
View file @
7f2b16d1
...
...
@@ -40,7 +40,6 @@ import com.fasterxml.jackson.databind.ser.std.StdSerializer;
/**
* The domain model for all registered application at the spring boot admin application.
*/
@JsonDeserialize
(
using
=
Application
.
Deserializer
.
class
)
public
class
Application
implements
Serializable
{
private
static
final
long
serialVersionUID
=
2L
;
...
...
@@ -51,7 +50,6 @@ public class Application implements Serializable {
private
final
String
serviceUrl
;
private
final
StatusInfo
statusInfo
;
private
final
String
source
;
@JsonSerialize
(
using
=
Application
.
MetadataSerializer
.
class
)
private
final
Map
<
String
,
String
>
metadata
;
private
final
Info
info
;
...
...
@@ -263,83 +261,4 @@ public class Application implements Serializable {
}
return
true
;
}
public
static
class
Deserializer
extends
StdDeserializer
<
Application
>
{
private
static
final
long
serialVersionUID
=
1L
;
protected
Deserializer
()
{
super
(
Application
.
class
);
}
@Override
public
Application
deserialize
(
JsonParser
p
,
DeserializationContext
ctxt
)
throws
IOException
,
JsonProcessingException
{
JsonNode
node
=
p
.
readValueAsTree
();
Builder
builder
=
create
(
node
.
get
(
"name"
).
asText
());
if
(
node
.
has
(
"url"
))
{
String
url
=
node
.
get
(
"url"
).
asText
();
builder
.
withHealthUrl
(
url
.
replaceFirst
(
"/+$"
,
""
)
+
"/health"
)
.
withManagementUrl
(
url
);
}
else
{
if
(
node
.
has
(
"healthUrl"
))
{
builder
.
withHealthUrl
(
node
.
get
(
"healthUrl"
).
asText
());
}
if
(
node
.
has
(
"managementUrl"
))
{
builder
.
withManagementUrl
(
node
.
get
(
"managementUrl"
).
asText
());
}
if
(
node
.
has
(
"serviceUrl"
))
{
builder
.
withServiceUrl
(
node
.
get
(
"serviceUrl"
).
asText
());
}
}
if
(
node
.
has
(
"metadata"
))
{
Iterator
<
Entry
<
String
,
JsonNode
>>
it
=
node
.
get
(
"metadata"
).
fields
();
while
(
it
.
hasNext
())
{
Entry
<
String
,
JsonNode
>
entry
=
it
.
next
();
builder
.
addMetadata
(
entry
.
getKey
(),
entry
.
getValue
().
asText
());
}
}
return
builder
.
build
();
}
}
public
static
class
MetadataSerializer
extends
StdSerializer
<
Map
<
String
,
String
>>
{
private
static
final
long
serialVersionUID
=
1L
;
private
static
Pattern
[]
keysToSanitize
=
createPatterns
(
".*password$"
,
".*secret$"
,
".*key$"
,
".*$token$"
,
".*credentials.*"
,
".*vcap_services$"
);
@SuppressWarnings
(
"unchecked"
)
public
MetadataSerializer
()
{
super
((
Class
<
Map
<
String
,
String
>>)
(
Class
<?>)
Map
.
class
);
}
private
static
Pattern
[]
createPatterns
(
String
...
keys
)
{
Pattern
[]
patterns
=
new
Pattern
[
keys
.
length
];
for
(
int
i
=
0
;
i
<
keys
.
length
;
i
++)
{
patterns
[
i
]
=
Pattern
.
compile
(
keys
[
i
],
Pattern
.
CASE_INSENSITIVE
);
}
return
patterns
;
}
@Override
public
void
serialize
(
Map
<
String
,
String
>
value
,
JsonGenerator
gen
,
SerializerProvider
provider
)
throws
IOException
{
gen
.
writeStartObject
();
for
(
Entry
<
String
,
String
>
entry
:
value
.
entrySet
())
{
gen
.
writeStringField
(
entry
.
getKey
(),
sanitize
(
entry
.
getKey
(),
entry
.
getValue
()));
}
gen
.
writeEndObject
();
}
private
String
sanitize
(
String
key
,
String
value
)
{
for
(
Pattern
pattern
:
MetadataSerializer
.
keysToSanitize
)
{
if
(
pattern
.
matcher
(
key
).
matches
())
{
return
(
value
==
null
?
null
:
"******"
);
}
}
return
value
;
}
}
}
spring-boot-admin-server/src/test/java/de/codecentric/boot/admin/jackson/ApplicationJacksonTest.java
0 → 100644
View file @
7f2b16d1
package
de
.
codecentric
.
boot
.
admin
.
jackson
;
import
de.codecentric.boot.admin.model.Application
;
import
java.util.Collections
;
import
org.json.JSONObject
;
import
org.junit.Assert
;
import
org.junit.Test
;
import
org.springframework.http.converter.json.Jackson2ObjectMapperBuilder
;
import
com.fasterxml.jackson.core.JsonProcessingException
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
com.fasterxml.jackson.databind.module.SimpleModule
;
import
static
org
.
hamcrest
.
CoreMatchers
.
containsString
;
import
static
org
.
hamcrest
.
Matchers
.
is
;
import
static
org
.
hamcrest
.
Matchers
.
not
;
import
static
org
.
hamcrest
.
Matchers
.
nullValue
;
public
class
ApplicationJacksonTest
{
private
final
SimpleModule
module
=
new
SimpleModule
()
//
.
addDeserializer
(
Application
.
class
,
new
ApplicationDeserializer
())
.
setSerializerModifier
(
new
ApplicationBeanSerializerModifier
(
new
SanitizingMapSerializer
(
new
String
[]{
".*password$"
})));
private
final
ObjectMapper
objectMapper
=
Jackson2ObjectMapperBuilder
.
json
().
modules
(
module
).
build
();
@Test
public
void
test_1_2_json_format
()
throws
Exception
{
String
json
=
new
JSONObject
().
put
(
"name"
,
"test"
).
put
(
"url"
,
"http://test"
).
toString
();
Application
value
=
objectMapper
.
readValue
(
json
,
Application
.
class
);
Assert
.
assertThat
(
value
.
getName
(),
is
(
"test"
));
Assert
.
assertThat
(
value
.
getManagementUrl
(),
is
(
"http://test"
));
Assert
.
assertThat
(
value
.
getHealthUrl
(),
is
(
"http://test/health"
));
Assert
.
assertThat
(
value
.
getServiceUrl
(),
nullValue
());
}
@Test
public
void
test_1_4_json_format
()
throws
Exception
{
String
json
=
new
JSONObject
().
put
(
"name"
,
"test"
)
.
put
(
"managementUrl"
,
"http://test"
)
.
put
(
"healthUrl"
,
"http://health"
)
.
put
(
"serviceUrl"
,
"http://service"
)
.
put
(
"statusInfo"
,
new
JSONObject
().
put
(
"status"
,
"UNKNOWN"
))
.
toString
();
Application
value
=
objectMapper
.
readValue
(
json
,
Application
.
class
);
Assert
.
assertThat
(
value
.
getName
(),
is
(
"test"
));
Assert
.
assertThat
(
value
.
getManagementUrl
(),
is
(
"http://test"
));
Assert
.
assertThat
(
value
.
getHealthUrl
(),
is
(
"http://health"
));
Assert
.
assertThat
(
value
.
getServiceUrl
(),
is
(
"http://service"
));
}
@Test
public
void
test_1_5_json_format
()
throws
Exception
{
String
json
=
new
JSONObject
().
put
(
"name"
,
"test"
)
.
put
(
"managementUrl"
,
"http://test"
)
.
put
(
"healthUrl"
,
"http://health"
)
.
put
(
"serviceUrl"
,
"http://service"
)
.
put
(
"metadata"
,
new
JSONObject
().
put
(
"labels"
,
"foo,bar"
))
.
toString
();
Application
value
=
objectMapper
.
readValue
(
json
,
Application
.
class
);
Assert
.
assertThat
(
value
.
getName
(),
is
(
"test"
));
Assert
.
assertThat
(
value
.
getManagementUrl
(),
is
(
"http://test"
));
Assert
.
assertThat
(
value
.
getHealthUrl
(),
is
(
"http://health"
));
Assert
.
assertThat
(
value
.
getServiceUrl
(),
is
(
"http://service"
));
Assert
.
assertThat
(
value
.
getMetadata
(),
is
(
Collections
.
singletonMap
(
"labels"
,
"foo,bar"
)));
}
@Test
public
void
test_onlyHealthUrl
()
throws
Exception
{
String
json
=
new
JSONObject
().
put
(
"name"
,
"test"
).
put
(
"healthUrl"
,
"http://test"
).
toString
();
Application
value
=
objectMapper
.
readValue
(
json
,
Application
.
class
);
Assert
.
assertThat
(
value
.
getName
(),
is
(
"test"
));
Assert
.
assertThat
(
value
.
getHealthUrl
(),
is
(
"http://test"
));
Assert
.
assertThat
(
value
.
getManagementUrl
(),
nullValue
());
Assert
.
assertThat
(
value
.
getServiceUrl
(),
nullValue
());
}
@Test
(
expected
=
IllegalArgumentException
.
class
)
public
void
test_name_expected
()
throws
Exception
{
String
json
=
new
JSONObject
().
put
(
"name"
,
""
)
.
put
(
"managementUrl"
,
"http://test"
)
.
put
(
"healthUrl"
,
"http://health"
)
.
put
(
"serviceUrl"
,
"http://service"
)
.
toString
();
objectMapper
.
readValue
(
json
,
Application
.
class
);
}
@Test
(
expected
=
IllegalArgumentException
.
class
)
public
void
test_healthUrl_expected
()
throws
Exception
{
String
json
=
new
JSONObject
().
put
(
"name"
,
"test"
)
.
put
(
"managementUrl"
,
"http://test"
)
.
put
(
"healthUrl"
,
""
)
.
put
(
"serviceUrl"
,
"http://service"
)
.
toString
();
objectMapper
.
readValue
(
json
,
Application
.
class
);
}
@Test
public
void
test_sanitize_metadata
()
throws
JsonProcessingException
{
Application
app
=
Application
.
create
(
"test"
)
.
withHealthUrl
(
"http://health"
)
.
addMetadata
(
"PASSWORD"
,
"qwertz123"
)
.
addMetadata
(
"user"
,
"humptydumpty"
)
.
build
();
String
json
=
objectMapper
.
writeValueAsString
(
app
);
Assert
.
assertThat
(
json
,
not
(
containsString
(
"qwertz123"
)));
Assert
.
assertThat
(
json
,
containsString
(
"humptydumpty"
));
}
}
\ No newline at end of file
spring-boot-admin-server/src/test/java/de/codecentric/boot/admin/model/ApplicationTest.java
View file @
7f2b16d1
package
de
.
codecentric
.
boot
.
admin
.
model
;
import
static
org
.
hamcrest
.
CoreMatchers
.
containsString
;
import
org.junit.Test
;
import
static
org
.
hamcrest
.
Matchers
.
is
;
import
static
org
.
hamcrest
.
Matchers
.
not
;
import
static
org
.
hamcrest
.
Matchers
.
nullValue
;
import
static
org
.
junit
.
Assert
.
assertThat
;
import
java.util.Collections
;
import
org.json.JSONObject
;
import
org.junit.Test
;
import
org.springframework.http.converter.json.Jackson2ObjectMapperBuilder
;
import
com.fasterxml.jackson.core.JsonProcessingException
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
public
class
ApplicationTest
{
private
ObjectMapper
objectMapper
=
Jackson2ObjectMapperBuilder
.
json
().
build
();
@Test
public
void
test_1_2_json_format
()
throws
Exception
{
String
json
=
new
JSONObject
().
put
(
"name"
,
"test"
).
put
(
"url"
,
"http://test"
).
toString
();
Application
value
=
objectMapper
.
readValue
(
json
,
Application
.
class
);
assertThat
(
value
.
getName
(),
is
(
"test"
));
assertThat
(
value
.
getManagementUrl
(),
is
(
"http://test"
));
assertThat
(
value
.
getHealthUrl
(),
is
(
"http://test/health"
));
assertThat
(
value
.
getServiceUrl
(),
nullValue
());
}
@Test
public
void
test_1_4_json_format
()
throws
Exception
{
String
json
=
new
JSONObject
().
put
(
"name"
,
"test"
).
put
(
"managementUrl"
,
"http://test"
)
.
put
(
"healthUrl"
,
"http://health"
).
put
(
"serviceUrl"
,
"http://service"
)
.
put
(
"statusInfo"
,
new
JSONObject
().
put
(
"status"
,
"UNKNOWN"
)).
toString
();
Application
value
=
objectMapper
.
readValue
(
json
,
Application
.
class
);
assertThat
(
value
.
getName
(),
is
(
"test"
));
assertThat
(
value
.
getManagementUrl
(),
is
(
"http://test"
));
assertThat
(
value
.
getHealthUrl
(),
is
(
"http://health"
));
assertThat
(
value
.
getServiceUrl
(),
is
(
"http://service"
));
}
@Test
public
void
test_1_5_json_format
()
throws
Exception
{
String
json
=
new
JSONObject
().
put
(
"name"
,
"test"
).
put
(
"managementUrl"
,
"http://test"
)
.
put
(
"healthUrl"
,
"http://health"
).
put
(
"serviceUrl"
,
"http://service"
)
.
put
(
"metadata"
,
new
JSONObject
().
put
(
"labels"
,
"foo,bar"
)).
toString
();
Application
value
=
objectMapper
.
readValue
(
json
,
Application
.
class
);
assertThat
(
value
.
getName
(),
is
(
"test"
));
assertThat
(
value
.
getManagementUrl
(),
is
(
"http://test"
));
assertThat
(
value
.
getHealthUrl
(),
is
(
"http://health"
));
assertThat
(
value
.
getServiceUrl
(),
is
(
"http://service"
));
assertThat
(
value
.
getMetadata
(),
is
(
Collections
.
singletonMap
(
"labels"
,
"foo,bar"
)));
}
@Test
public
void
test_onlyHealthUrl
()
throws
Exception
{
String
json
=
new
JSONObject
().
put
(
"name"
,
"test"
).
put
(
"healthUrl"
,
"http://test"
)
.
toString
();
Application
value
=
objectMapper
.
readValue
(
json
,
Application
.
class
);
assertThat
(
value
.
getName
(),
is
(
"test"
));
assertThat
(
value
.
getHealthUrl
(),
is
(
"http://test"
));
assertThat
(
value
.
getManagementUrl
(),
nullValue
());
assertThat
(
value
.
getServiceUrl
(),
nullValue
());
}
@Test
(
expected
=
IllegalArgumentException
.
class
)
public
void
test_name_expected
()
throws
Exception
{
String
json
=
new
JSONObject
().
put
(
"name"
,
""
).
put
(
"managementUrl"
,
"http://test"
)
.
put
(
"healthUrl"
,
"http://health"
).
put
(
"serviceUrl"
,
"http://service"
).
toString
();
objectMapper
.
readValue
(
json
,
Application
.
class
);
}
@Test
(
expected
=
IllegalArgumentException
.
class
)
public
void
test_healthUrl_expected
()
throws
Exception
{
String
json
=
new
JSONObject
().
put
(
"name"
,
"test"
).
put
(
"managementUrl"
,
"http://test"
)
.
put
(
"healthUrl"
,
""
).
put
(
"serviceUrl"
,
"http://service"
).
toString
();
objectMapper
.
readValue
(
json
,
Application
.
class
);
}
@Test
public
void
test_sanitize_metadata
()
throws
JsonProcessingException
{
Application
app
=
Application
.
create
(
"test"
).
withHealthUrl
(
"http://health"
)
.
addMetadata
(
"PASSWORD"
,
"qwertz123"
).
addMetadata
(
"user"
,
"humptydumpty"
).
build
();
String
json
=
objectMapper
.
writeValueAsString
(
app
);
assertThat
(
json
,
not
(
containsString
(
"qwertz123"
)));
assertThat
(
json
,
containsString
(
"humptydumpty"
));
}
@Test
public
void
test_equals_hashCode
()
{
Application
a1
=
Application
.
create
(
"foo"
).
withHealthUrl
(
"healthUrl"
)
.
withManagementUrl
(
"mgmt"
).
withServiceUrl
(
"svc"
).
withId
(
"id"
).
build
();
Application
a2
=
Application
.
create
(
"foo"
).
withHealthUrl
(
"healthUrl"
)
.
withManagementUrl
(
"mgmt"
).
withServiceUrl
(
"svc"
).
withId
(
"id"
).
build
();
assertThat
(
a1
,
is
(
a2
));
assertThat
(
a1
.
hashCode
(),
is
(
a2
.
hashCode
()));
Application
a3
=
Application
.
create
(
"foo"
).
withHealthUrl
(
"healthUrl2"
)
.
withManagementUrl
(
"mgmt"
).
withServiceUrl
(
"svc"
).
withId
(
"other"
).
build
();
assertThat
(
a1
,
not
(
is
(
a3
)));
assertThat
(
a2
,
not
(
is
(
a3
)));
}
@Test
public
void
test_builder_copy
()
{
Application
app
=
Application
.
create
(
"App"
).
withId
(
"-id-"
).
withHealthUrl
(
"http://health"
)
.
withManagementUrl
(
"http://mgmgt"
).
withServiceUrl
(
"http://svc"
)
.
withStatusInfo
(
StatusInfo
.
ofUp
()).
build
();
Application
copy
=
Application
.
copyOf
(
app
).
build
();
assertThat
(
app
,
is
(
copy
));
}
@Test
public
void
test_equals_hashCode
()
{
Application
a1
=
Application
.
create
(
"foo"
)
.
withHealthUrl
(
"healthUrl"
)
.
withManagementUrl
(
"mgmt"
)
.
withServiceUrl
(
"svc"
)
.
withId
(
"id"
)
.
build
();
Application
a2
=
Application
.
create
(
"foo"
)
.
withHealthUrl
(
"healthUrl"
)
.
withManagementUrl
(
"mgmt"
)
.
withServiceUrl
(
"svc"
)
.
withId
(
"id"
)
.
build
();
assertThat
(
a1
,
is
(
a2
));
assertThat
(
a1
.
hashCode
(),
is
(
a2
.
hashCode
()));
Application
a3
=
Application
.
create
(
"foo"
)
.
withHealthUrl
(
"healthUrl2"
)
.
withManagementUrl
(
"mgmt"
)
.
withServiceUrl
(
"svc"
)
.
withId
(
"other"
)
.
build
();
assertThat
(
a1
,
not
(
is
(
a3
)));
assertThat
(
a2
,
not
(
is
(
a3
)));
}
@Test
public
void
test_builder_copy
()
{
Application
app
=
Application
.
create
(
"App"
)
.
withId
(
"-id-"
)
.
withHealthUrl
(
"http://health"
)
.
withManagementUrl
(
"http://mgmgt"
)
.
withServiceUrl
(
"http://svc"
)
.
withStatusInfo
(
StatusInfo
.
ofUp
())
.
build
();
Application
copy
=
Application
.
copyOf
(
app
).
build
();
assertThat
(
app
,
is
(
copy
));
}
}
\ No newline at end of file
spring-boot-admin-server/src/test/java/de/codecentric/boot/admin/registry/web/RegistryControllerTest.java
View file @
7f2b16d1
...
...
@@ -35,12 +35,18 @@ import org.mockito.internal.matchers.Matches;
import
org.springframework.context.ApplicationEventPublisher
;
import
org.springframework.http.HttpHeaders
;
import
org.springframework.http.MediaType
;
import
org.springframework.http.converter.json.Jackson2ObjectMapperBuilder
;
import
org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
;
import
org.springframework.test.web.servlet.MockMvc
;
import
org.springframework.test.web.servlet.MvcResult
;
import
org.springframework.test.web.servlet.setup.MockMvcBuilders
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
com.fasterxml.jackson.databind.module.SimpleModule
;
import
com.jayway.jsonpath.JsonPath
;
import
de.codecentric.boot.admin.jackson.ApplicationDeserializer
;
import
de.codecentric.boot.admin.model.Application
;
import
de.codecentric.boot.admin.registry.ApplicationRegistry
;
import
de.codecentric.boot.admin.registry.HashingApplicationUrlIdGenerator
;
import
de.codecentric.boot.admin.registry.store.SimpleApplicationStore
;
...
...
@@ -70,7 +76,11 @@ public class RegistryControllerTest {
ApplicationRegistry
registry
=
new
ApplicationRegistry
(
new
SimpleApplicationStore
(),
new
HashingApplicationUrlIdGenerator
());
registry
.
setApplicationEventPublisher
(
Mockito
.
mock
(
ApplicationEventPublisher
.
class
));
mvc
=
MockMvcBuilders
.
standaloneSetup
(
new
RegistryController
(
registry
)).
build
();
SimpleModule
module
=
new
SimpleModule
().
addDeserializer
(
Application
.
class
,
new
ApplicationDeserializer
());
ObjectMapper
objectMapper
=
Jackson2ObjectMapperBuilder
.
json
().
modules
(
module
).
build
();
mvc
=
MockMvcBuilders
.
standaloneSetup
(
new
RegistryController
(
registry
))
.
setMessageConverters
(
new
MappingJackson2HttpMessageConverter
(
objectMapper
))
.
build
();
}
@Test
...
...
@@ -78,7 +88,8 @@ public class RegistryControllerTest {
MvcResult
result
=
mvc
.
perform
(
post
(
"/api/applications"
).
contentType
(
MediaType
.
APPLICATION_JSON
).
content
(
APPLICATION_TEST_JSON
))
.
andExpect
(
status
().
isCreated
())
.
andExpect
(
header
().
string
(
HttpHeaders
.
LOCATION
,
new
Matches
(
"http://localhost/[0-9a-f]+"
)))
.
andExpect
(
header
().
string
(
HttpHeaders
.
LOCATION
,
new
Matches
(
"http://localhost/[0-9a-f]+"
)))
.
andExpect
(
jsonPath
(
"$.id"
).
isNotEmpty
())
.
andReturn
();
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment