blob: 0f1e85422656e704075295cae36098c7eaf9caa8 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The SF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.apache.sling.hc.support.impl;
import java.util.Arrays;
import java.util.List;
import javax.jcr.Credentials;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.SimpleCredentials;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.ConfigurationPolicy;
import org.apache.felix.scr.annotations.Properties;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.PropertyUnbounded;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.apache.sling.commons.osgi.PropertiesUtil;
import org.apache.sling.hc.api.HealthCheck;
import org.apache.sling.hc.api.Result;
import org.apache.sling.hc.util.FormattingResultLog;
import org.apache.sling.jcr.api.SlingRepository;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** {@link HealthCheck} that checks that Sling default logins fail.
* Used to verify that those logins are disabled on production systems */
@Component(
name="org.apache.sling.hc.support.DefaultLoginsHealthCheck",
configurationFactory=true,
policy=ConfigurationPolicy.REQUIRE,
metatype=true,
label="Apache Sling Default Logins Health Check",
description="Expects default logins to fail, used to verify " +
"that they are disabled on production systems")
@Properties({
@Property(name=HealthCheck.NAME,
label="Health Check Name", description="Name of this Health Check service."),
@Property(name=HealthCheck.TAGS, unbounded=PropertyUnbounded.ARRAY,
label="Health Check tags", description="List of tags for this Health Check service, used to select " +
"subsets of Health Check services for execution"),
@Property(name=HealthCheck.MBEAN_NAME,
label="MBean Name", description="Name of the MBean to create for this Health Check.")
})
@Service(value=HealthCheck.class)
public class DefaultLoginsHealthCheck implements HealthCheck {
private final Logger log = LoggerFactory.getLogger(getClass());
@Property(unbounded=PropertyUnbounded.ARRAY,
label="Login credentials",
description="Which credentials to check. Each one is in the format \"user:password\" " +
"like \"admin:admin\" for example. Do *not* put any confidential passwords here, the goal " +
"is just to check that the default/demo logins, which passwords are known anyway, are disabled.")
private static final String PROP_LOGINS = "logins";
private List<String> logins;
@Reference
private SlingRepository repository;
@Activate
public void activate(ComponentContext ctx) {
logins = Arrays.asList(PropertiesUtil.toStringArray(ctx.getProperties().get(PROP_LOGINS), new String[] {}));
log.info("Activated, logins={}", logins);
}
@Override
public Result execute() {
final FormattingResultLog resultLog = new FormattingResultLog();
int checked=0;
int failures=0;
for(String login : logins) {
final String [] parts = login.split(":");
if(parts.length != 2) {
resultLog.warn("Expected login in the form username:password, got [{}]", login);
continue;
}
checked++;
final String username = parts[0].trim();
final String password = parts[1].trim();
final Credentials creds = new SimpleCredentials(username, password.toCharArray());
Session s = null;
try {
s = repository.login(creds);
if(s != null) {
failures++;
resultLog.warn("Login as [{}] succeeded, was expecting it to fail", username);
} else {
resultLog.debug("Login as [{}] didn't throw an Exception but returned null Session", username);
}
} catch(RepositoryException re) {
resultLog.debug("Login as [{}] failed, as expected", username);
} finally {
if(s != null) {
s.logout();
}
}
}
if(checked==0) {
resultLog.warn("Did not check any logins, configured logins={}", logins);
} else if(failures != 0){
resultLog.warn("Checked {} logins, {} failures", checked, failures);
} else {
resultLog.debug("Checked {} logins, all successful", checked, failures);
}
return new Result(resultLog);
}
}