Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Set default web ports for console and rest #5624

Merged
merged 10 commits into from
Jan 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2011, 2022 Eurotech and/or its affiliates and others
* Copyright (c) 2011, 2024 Eurotech and/or its affiliates and others
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
Expand All @@ -13,6 +13,7 @@
*******************************************************************************/
package org.eclipse.kura.core.configuration;

import static java.util.Objects.isNull;
import static java.util.Objects.requireNonNull;

import java.io.File;
Expand Down Expand Up @@ -64,6 +65,7 @@
import org.eclipse.kura.marshalling.Marshaller;
import org.eclipse.kura.marshalling.Unmarshaller;
import org.eclipse.kura.system.SystemService;
import org.eclipse.kura.util.service.ServiceUtil;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
Expand Down Expand Up @@ -1232,103 +1234,99 @@ private ComponentConfiguration getConfigurableComponentConfiguration(String pid)

private ComponentConfiguration getSelfConfiguringComponentConfiguration(String pid) {
ComponentConfiguration cc = null;
final ServiceReference<?>[] refs = ServiceUtil.getServiceReferences(this.bundleContext,
SelfConfiguringComponent.class, null);

try {
ServiceReference<?>[] refs = this.ctx.getBundleContext().getServiceReferences((String) null, null);
if (refs != null) {
for (ServiceReference<?> ref : refs) {
String ppid = (String) ref.getProperty(KURA_SERVICE_PID);
if (pid.equals(ppid)) {
Object obj = this.ctx.getBundleContext().getService(ref);
try {
if (obj instanceof SelfConfiguringComponent) {
SelfConfiguringComponent selfConfigComp = null;
selfConfigComp = (SelfConfiguringComponent) obj;
try {
cc = selfConfigComp.getConfiguration();
if (cc.getPid() == null || !cc.getPid().equals(pid)) {
logger.error(
"Invalid pid for returned Configuration of SelfConfiguringComponent with pid: "
+ pid + ". Ignoring it.");
return null;
}

OCD ocd = cc.getDefinition();
if (ocd != null) {
List<AD> ads = ocd.getAD();

if (ads != null) {
for (AD ad : ads) {
String adId = ad.getId();
String adType = ad.getType().value();

if (adId == null) {
logger.error(
"null required id for AD for returned Configuration of SelfConfiguringComponent with pid: {}",
pid);
return null;
}
if (adType == null) {
logger.error(
"null required type for AD id: {} for returned Configuration of SelfConfiguringComponent with pid: {}",
adId, pid);
return null;
}

Map<String, Object> props = cc.getConfigurationProperties();
if (props != null) {
Object value = props.get(adId);
if (value != null) {
String propType;
if (!value.getClass().isArray()) {
propType = value.getClass().getSimpleName();
} else {
propType = value.getClass().getComponentType()
.getSimpleName();
}

try {
logger.debug(
"pid: {}, property name: {}, type: {}, value: {}",
pid, adId, propType, value);
Scalar propertyScalar = Scalar.fromValue(propType);
Scalar adScalar = Scalar.fromValue(adType);
if (propertyScalar != adScalar) {
logger.error(
"Type: {} for property named: {} does not match the AD type: {} for returned Configuration of SelfConfiguringComponent with pid: {}",
new Object[] { propType, adId, adType, pid });
return null;
}
} catch (IllegalArgumentException e) {
logger.error(
"Invalid class: {} for property named: {} for returned Configuration of SelfConfiguringComponent with pid: "
+ pid,
propType, adId);
return null;
}
}
}
}
}
}
} catch (KuraException e) {
logger.error(GETTING_CONFIGURATION_ERROR, pid, e);
}
} else {
logger.error("Component {} is not a SelfConfiguringComponent. Ignoring it.", obj);
}
} finally {
this.ctx.getBundleContext().ungetService(ref);
}
for (ServiceReference<?> ref : refs) {
String ppid = (String) ref.getProperty(KURA_SERVICE_PID);
final SelfConfiguringComponent selfConfigComp = (SelfConfiguringComponent) this.bundleContext
.getService(ref);
if (pid.equals(ppid)) {

cc = selfConfigComp.getConfiguration();
if (!isValidSelfConfiguringComponent(pid, cc)) {
return null;
}
}
}
} catch (InvalidSyntaxException e) {
} catch (KuraException e) {
logger.error(GETTING_CONFIGURATION_ERROR, pid, e);
} finally {
ServiceUtil.ungetServiceReferences(this.bundleContext, refs);
}

return cc;
}

private boolean isValidSelfConfiguringComponent(String pid, ComponentConfiguration cc) {

if (isNull(cc) || cc.getPid() == null || !cc.getPid().equals(pid)) {
logger.error(
"Invalid pid for returned Configuration of SelfConfiguringComponent with pid: {}. Ignoring it.",
pid);
return false;
}

OCD ocd = cc.getDefinition();
if (isNull(ocd) || isNull(ocd.getAD())) {
return false;
}

List<AD> ads = ocd.getAD();

for (AD ad : ads) {
String adId = ad.getId();
String adType = ad.getType().value();

if (isNull(adId) || isNull(adType)) {
logger.error(
"null required type for AD id: {} for returned Configuration of SelfConfiguringComponent with pid: {}",
adId, pid);
return false;
}

Map<String, Object> props = cc.getConfigurationProperties();
if (!isNull(props) && !isNull(props.get(adId)) && !isMatchingADType(pid, adId, adType, props.get(adId))) {
return false;
}
}
return true;
}

private boolean isMatchingADType(String pid, String adId, String adType, Object value) {
boolean result = false;
try {
logger.debug("pid: {}, property name: {}, value: {}", pid, adId, value);
Scalar propertyScalar = getScalarFromObject(value);
Scalar adScalar = Scalar.fromValue(adType);
if (propertyScalar != adScalar) {
logger.error(
"Type: {} for property named: {} does not match the AD type: {} for returned Configuration of SelfConfiguringComponent with pid: {}",
propertyScalar.name(), adId, adType, pid);
}
result = true;
} catch (IllegalArgumentException e) {
logger.error(
"Invalid class for property named: {} for returned Configuration of SelfConfiguringComponent with pid: {}",
adId, pid);
}
return result;
}

private Scalar getScalarFromObject(Object p) {
Class<?> clazz = p.getClass();
if (clazz.isArray()) {
Object[] tempArray = (Object[]) p;
if (tempArray.length > 0 && tempArray[0] != null) {
clazz = tempArray[0].getClass();
} else {
clazz = clazz.getComponentType();
}
}
return Scalar.fromValue(clazz.getSimpleName());
}

private TreeSet<Long> getSnapshotsInternal() {
// keeps the list of snapshots ordered
TreeSet<Long> ids = new TreeSet<>();
Expand Down Expand Up @@ -1901,10 +1899,7 @@ public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
if (obj == null || getClass() != obj.getClass()) {
return false;
}
TrackedComponentFactory other = (TrackedComponentFactory) obj;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
/*******************************************************************************
* Copyright (c) 2021, 2022 Eurotech and/or its affiliates and others
*
* Copyright (c) 2021, 2024 Eurotech and/or its affiliates and others
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
*
* SPDX-License-Identifier: EPL-2.0
*
*
* Contributors:
* Eurotech
*******************************************************************************/
Expand Down Expand Up @@ -45,10 +45,10 @@ public Object getValue() {
public void validate() {
FailureHandler.requireParameter(this.type, "type");

if (value instanceof List<?>) {
validateArrayProperty(type, (List<?>) value);
if (this.value instanceof List<?>) {
validateArrayProperty(this.type, (List<?>) this.value);
} else {
validateSingletonProperty(type, value);
validateSingletonProperty(this.type, this.value);
}
}

Expand Down Expand Up @@ -96,22 +96,35 @@ private static void validateSingletonProperty(final Scalar type, final Object va

public static Optional<PropertyDTO> fromConfigurationProperty(final Object property) {

return Optional.ofNullable(property).flatMap(p -> scalarFromClass(p.getClass()))
return Optional.ofNullable(property).flatMap(PropertyDTO::getScalarFromObject)
.map(type -> new PropertyDTO(configurationPropertyToDTOProperty(property), type));
}

private static Optional<Scalar> getScalarFromObject(Object p) {
Class<?> clazz = p.getClass();
if (clazz.isArray()) {
Object[] tempArray = (Object[]) p;
if (tempArray.length > 0 && tempArray[0] != null) {
clazz = tempArray[0].getClass();
} else {
clazz = clazz.getComponentType();
}
}
return scalarFromSingletonClass(clazz);
}

public Optional<Object> toConfigurationProperty() {
if (value == null) {
if (this.value == null) {
return Optional.empty();
}

final Optional<Object> asSingleton = singletonToProperty(value, type);
final Optional<Object> asSingleton = singletonToProperty(this.value, this.type);

if (asSingleton.isPresent()) {
return asSingleton;
}

return arrayToProperty(value, type);
return arrayToProperty(this.value, this.type);
}

@SuppressWarnings("unchecked")
Expand Down Expand Up @@ -233,7 +246,7 @@ private static Optional<Object> arrayToProperty(final Object propertyValue, fina
}
}

public static Optional<Scalar> scalarFormSingletonClass(final Class<?> clazz) {
public static Optional<Scalar> scalarFromSingletonClass(final Class<?> clazz) {
final Scalar result;

if (clazz == Boolean.class) {
Expand Down Expand Up @@ -263,14 +276,6 @@ public static Optional<Scalar> scalarFormSingletonClass(final Class<?> clazz) {
return Optional.of(result);
}

public static Optional<Scalar> scalarFromClass(final Class<?> clazz) {
if (clazz.isArray()) {
return scalarFormSingletonClass(clazz.getComponentType());
} else {
return scalarFormSingletonClass(clazz);
}
}

private static Object configurationPropertyToDTOProperty(final Object property) {
if (property instanceof Password) {
return new String(((Password) property).getPassword());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
type="Integer"
cardinality="3"
required="false"
default="443,4443"
min="1"
max="65535"
description="If set to a non empty list, REST API access will be allowed only on the specified ports. If set to an empty list, access will be allowed on all ports. Please make sure that the allowed ports are open in HttpService and Firewall configuration.">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ public class ConsoleOptions {
new AdBuilder("allowed.ports", "Allowed ports", Tscalar.INTEGER) //
.setRequired(false) //
.setCardinality(3) //
.setDefault("443,4443") //
.setDescription(
"If set to a non empty list, Web Console access will be allowed only on the specified ports. If set to an empty list, access will be allowed on all ports. Please make sure that the allowed ports are open in HttpService and Firewall configuration.") //
.build(), //
Expand Down
Loading
Loading